如何在Redis中實現緩存功能

Redis 是一種高性能的鍵值存儲系統,廣泛用于實現緩存功能。它通過將數據存儲在內存中,能夠快速讀寫數據,從而顯著提高應用程序的性能。在Redis中實現緩存功能需要結合數據讀寫策略、失效機制及性能優化方案。

一、Redis作為緩存的核心優勢

  1. 高性能讀寫:內存存儲+單線程架構,支持10萬+QPS。
  2. 豐富數據結構String(最常用)、HashList等適配不同場景。
  3. 過期機制:自動淘汰過期數據,減少內存占用。
  4. 高可用性:通過哨兵(Sentinel)或集群(Cluster)實現故障轉移。

二、Redis緩存實現核心流程

1. 基礎緩存讀寫模型(Cache-Aside模式)
import redis
import time
from functools import wraps# 連接Redis
redis_client = redis.Redis(host='localhost', port=6379, db=0)def get_data_from_cache_or_db(key, db_query_func, cache_ttl=3600):"""從緩存獲取數據,若不存在則查詢數據庫并寫入緩存"""# 讀緩存cache_data = redis_client.get(key)if cache_data:return cache_data.decode('utf-8')  # 反序列化# 緩存未命中,查詢數據庫db_data = db_query_func()if db_data:# 寫入緩存(設置過期時間)redis_client.setex(key, cache_ttl, db_data)return db_data# 示例:查詢用戶信息
def get_user_info(user_id):def query_db():# 實際項目中調用數據庫查詢return f"user:{user_id}:info"return get_data_from_cache_or_db(f"user:{user_id}", query_db)
2. 緩存更新策略

Redis主要采用以下的緩存更新策略:

  • 過期淘汰(推薦):通過EXPIRESETEX設置TTL,適用于非實時數據。
  • 主動更新:數據變更時同步更新緩存(需注意并發問題)。
  • 懶加載更新:下次讀取時刷新緩存(如上述代碼)。
3. 并發場景處理(防緩存擊穿)
def cache_with_lock(key, db_func, lock_ttl=10, cache_ttl=3600):"""使用分布式鎖避免緩存擊穿(多個請求同時查詢數據庫)"""lock_key = f"lock:{key}"# 嘗試獲取鎖(SETNX:僅當key不存在時設置)acquired = redis_client.set(lock_key, "1", nx=True,  # 不存在時才設置ex=lock_ttl  # 鎖過期時間,防止死鎖)if acquired:try:# 鎖獲取成功,查詢數據庫data = db_func()if data:redis_client.setex(key, cache_ttl, data)return datafinally:# 釋放鎖(確保原子性,避免誤刪其他線程的鎖)redis_client.delete(lock_key)else:# 鎖被占用,等待重試或直接返回緩存(若有)time.sleep(0.1)  # 短暫休眠后重試return redis_client.get(key)

三、緩存常見問題及解決方案

問題類型問題描述影響解決方案技術實現要點適用場景性能影響一致性級別
緩存穿透大量請求查詢不存在的Key,穿透緩存直達數據庫數據庫壓力驟增,可能導致服務崩潰1. 布隆過濾器(Bloom Filter)
2. 緩存空值(Null值緩存)
1. 布隆過濾器預加載所有可能的Key
2. 緩存空值設置短TTL(如60秒)
高并發且查詢Key分散的場景1. 布隆過濾器增加約0.5ms延遲
2. 空值緩存增加內存占用
最終一致性(空值可能短暫存在)
緩存雪崩大量緩存Key在同一時間過期,導致請求全部轉向數據庫數據庫瞬時壓力過大,服務響應緩慢甚至不可用1. 隨機化TTL(基礎時間+隨機偏移)
2. 熱點數據永不過期(手動更新)
1. TTL=基礎時間(如3600秒)+隨機數(0-600秒)
2. 定期后臺線程更新熱點數據
有明確批量緩存更新的場景隨機化TTL可能導致部分緩存提前過期,增加數據庫訪問頻率最終一致性(熱點數據手動更新時可能不一致)
緩存擊穿單個熱點Key過期時,大量請求同時查詢該Key,導致數據庫壓力激增數據庫瞬間壓力過大,可能引發連鎖反應1. 分布式鎖(如RedLock)
2. 互斥更新(僅允許一個請求更新緩存)
1. 使用SETNX+EXPIRE原子操作實現鎖
2. 鎖超時時間設置為業務處理時間的2倍
熱點Key訪問頻率極高的場景(如秒殺商品)加鎖操作增加約1-3ms延遲,可能導致部分請求等待強一致性(鎖持有期間)
緩存與數據庫不一致緩存與數據庫數據不一致,可能導致業務邏輯錯誤數據展示異常,業務計算結果錯誤1. 延時雙刪(先刪緩存,更新數據庫,延遲后再刪緩存)
2. 消息隊列異步同步
1. 延遲時間設置為主從復制延遲的2倍(如500ms)
2. 消息隊列保證至少一次投遞
對數據一致性要求較高的場景(如庫存、余額)延時雙刪增加約1ms延遲,消息隊列增加約50-100ms異步延遲最終一致性(延時雙刪)/ 強一致性(消息隊列同步成功后)
緩存污染冷門數據占用緩存空間,導致熱點數據被淘汰緩存命中率下降,頻繁訪問數據庫1. 使用LFU(最不經常使用)淘汰策略
2. 定期清理冷門數據
1. 配置maxmemory-policy=allkeys-lfu
2. 基于訪問頻率設置數據優先級
數據訪問分布不均,有明顯冷熱數據區分的場景LFU算法比LRU略消耗CPU資源(約5%)N/A
緩存失效風暴當某個Key失效時,大量請求同時重建緩存,造成系統資源浪費CPU、內存資源被過度占用,服務響應緩慢1. 永不過期(邏輯過期)
2. 后臺異步更新緩存
1. 緩存不設置物理過期時間,通過邏輯標記控制更新
2. 定時任務提前更新即將過期的緩存
高并發且緩存重建代價高的場景(如復雜計算結果)后臺更新增加系統負載,但分散在非高峰期最終一致性(更新過程中可能不一致)
緩存雪崩(預熱不足)系統重啟或緩存集群故障恢復后,大量請求直接訪問數據庫數據庫壓力過大,恢復時間延長1. 緩存預熱(啟動時加載熱點數據)
2. 分級恢復(按優先級加載緩存)
1. 啟動腳本批量加載熱點數據到緩存
2. 按業務重要性分批次恢復緩存
系統重啟頻繁或緩存集群易故障的場景預熱過程可能占用啟動時間(如30-60秒)最終一致性(預熱過程中可能不一致)
緩存擊穿(并發重建)多個請求同時發現緩存失效,并發重建緩存資源浪費,可能導致數據庫瞬時壓力過大1. 單線程重建(分布式鎖)
2. 提前刷新(在緩存過期前主動更新)
1. 使用Redis的SETNX命令實現互斥鎖
2. 定時任務在緩存過期前50%時間點更新
熱點數據更新頻率較低的場景加鎖操作增加約1-3ms延遲強一致性(鎖持有期間)
緩存穿透(惡意攻擊)攻擊者故意請求不存在的Key,耗盡數據庫資源數據庫服務不可用,業務中斷1. 布隆過濾器+限流
2. IP黑名單+WAF防護
1. 布隆過濾器攔截無效請求
2. 對單個IP請求頻率超過閾值(如1000次/秒)進行限流
開放API接口或易受攻擊的場景限流可能導致部分合法請求被拒絕N/A
緩存與數據庫雙寫不一致同時更新緩存和數據庫時,因網絡等原因導致兩者不一致數據展示異常,業務計算結果錯誤1. 先更新數據庫,再刪除緩存(Cache-Aside模式)
2. 重試機制(消息隊列)
1. 更新數據庫后刪除緩存,失敗時記錄日志并通過消息隊列重試
2. 設置最大重試次數(如3次)
對數據一致性要求較高的場景(如訂單、支付)重試機制增加系統復雜度和延遲(約10-50ms)最終一致性(重試成功后)
1. 緩存穿透(查詢穿透到DB)
  • 問題:大量請求查詢不存在的Key,擊穿緩存直達數據庫。
  • 解決方案
    • 空值緩存:對不存在的Key也寫入緩存(如setex key 60 "")。
    • 布隆過濾器(Bloom Filter):提前過濾無效Key(需引入Redis模塊或外部組件)。
2. 緩存雪崩(大量Key同時過期)
  • 問題:大量緩存同時失效,導致DB壓力驟增。
  • 解決方案
    • 隨機TTL:給Key設置基礎時間+隨機偏移量(如3600+random(600))。
    • 熱點數據永不過期:手動維護緩存更新,避免自動過期。
    • 多級緩存:本地緩存(如Memcached)+ Redis緩存,分擔壓力。
3. 緩存擊穿(熱點Key過期)
  • 問題:單Key失效時,大量請求同時查詢DB。
  • 解決方案
    • 分布式鎖:如前文cache_with_lock函數,確保同一時間僅一個請求查詢DB。
    • 互斥更新:使用Lua腳本保證更新操作原子性。
4. 緩存與數據庫一致性
  • 雙寫策略
    1. 先更新DB,再更新緩存:并發場景可能導致緩存與DB不一致。
    2. 先更新DB,再刪除緩存:更安全的方式,但需處理刪除失敗(可結合消息隊列重試)。
  • 延時雙刪
    def update_data_and_cache(db_key, new_data):# 1. 更新數據庫update_db(db_key, new_data)# 2. 刪除緩存redis_client.delete(f"cache:{db_key}")# 3. 延時一段時間后再次刪除緩存(解決主從復制延遲問題)time.sleep(0.5)redis_client.delete(f"cache:{db_key}")
    
5.解決方案選擇建議
  1. 優先預防:通過合理的TTL設置(隨機化+熱點數據永不過期)預防雪崩和擊穿
  2. 防御穿透:高并發場景必須部署布隆過濾器+空值緩存
  3. 保證一致性:關鍵業務采用"先更新數據庫,再刪除緩存+重試機制"
  4. 性能優先:對一致性要求不高的場景(如瀏覽量統計)使用異步寫入
  5. 監控預警:實時監控緩存命中率(目標>90%)、Redis內存使用率(閾值80%)、數據庫QPS波動

四、緩存架構與性能優化

1. 架構設計優化
  • 單節點模式:適用于測試環境,簡單但無高可用。
  • 哨兵模式(Sentinel)
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel down-after-milliseconds mymaster 5000
    
  • 集群模式(Cluster):分片存儲,支持橫向擴展(推薦生產環境)。
2. 性能優化
  • 批量操作:使用MGETPIPELINE減少網絡往返:
    # 批量獲取
    keys = ["user:1", "user:2", "user:3"]
    results = redis_client.mget(keys)# 管道批量操作
    with redis_client.pipeline() as pipe:for key in keys:pipe.get(key)results = pipe.execute()
    
  • 壓縮存儲:對大文本數據使用LZ4等算法壓縮后存入Redis。
  • 熱點數據預熱:啟動時主動加載高頻訪問數據到緩存。

五、Redis緩存應用注意事項

  1. 緩存命中率監控:通過INFO cache查看keyspace_hitskeyspace_misses計算命中率(目標>90%)。
  2. 內存淘汰策略:根據業務選擇volatile-lru(淘汰帶過期時間的LRU數據)或allkeys-lfu(淘汰低頻訪問數據)。
  3. 冷熱數據分離:將高頻訪問數據存儲在獨立Redis實例。
  4. 緩存降級:當Redis故障時,直接訪問DB并返回基礎數據,避免服務雪崩。
  5. 數據類型選擇
    • 簡單字符串:使用String(如用戶ID->信息)。
    • 結構化數據:使用Hash(如user:1包含nameage字段)。
    • 列表數據:使用List(如最新評論列表)。

六、實戰案例:用戶信息緩存

import redis
import jsonclass UserCache:def __init__(self, host='localhost', port=6379, db=0):self.redis_client = redis.Redis(host, port, db)self.cache_prefix = "user:"self.default_ttl = 3600  # 1小時def get_user(self, user_id):"""獲取用戶信息(先查緩存,再查DB)"""cache_key = f"{self.cache_prefix}{user_id}"user_data = self.redis_client.get(cache_key)if user_data:return json.loads(user_data)# 緩存未命中,查詢DB(實際項目中替換為真實DB查詢)user_data = self._query_db(user_id)if user_data:self.redis_client.setex(cache_key, self.default_ttl, json.dumps(user_data))return user_datadef update_user(self, user_id, user_data):"""更新用戶信息(先更新DB,再刪除緩存)"""# 1. 更新DBself._update_db(user_id, user_data)# 2. 刪除緩存(避免臟數據)cache_key = f"{self.cache_prefix}{user_id}"self.redis_client.delete(cache_key)def _query_db(self, user_id):"""模擬數據庫查詢"""return {"id": user_id, "name": f"user_{user_id}", "create_time": time.time()}def _update_db(self, user_id, user_data):"""模擬數據庫更新"""print(f"Updating user {user_id} in database...")

通過以上方案,可在Redis中實現高效、穩定的緩存功能。實際應用中需根據業務場景調整策略,同時結合監控系統(如Prometheus+Grafana)實時追蹤緩存性能與健康狀態。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/910082.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/910082.shtml
英文地址,請注明出處:http://en.pswp.cn/news/910082.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Kafka消費者客戶端源碼深度解析:從架構到核心流程

在Kafka生態系統中,消費者客戶端作為數據消費的入口,其設計與實現直接影響數據處理的效率和可靠性。本文將深入Kafka消費者客戶端源碼,通過核心組件解析、流程拆解與源碼分析,揭示其高性能消費背后的技術奧秘,并輔以架…

從0開始學習R語言--Day26--因果推斷

很多時候我們在探討數據的相關性問題時,很容易會忽略到底是數據本身的特點還是真的是因為特征的區分導致的不同,從而誤以為是特征起的效果比較大。 這就好比測試一款新藥是否真的能治病,假如吃藥的患者康復的更快,那到底是因為藥…

Python 中布爾值的使用:掌握邏輯判斷的核心

在 Python 中,布爾值(bool)是進行邏輯判斷的基礎。布爾值只有兩個可能的值:True 和 False。通過布爾值,你可以實現條件判斷、循環控制以及其他邏輯操作。今天,就讓我們一起深入探討如何在 Python 中使用布爾…

IDEA 中 Tomcat 部署 Java Web 項目(Maven 多模塊 非 Maven 通用版)(linux+windows)

引言 Java Web 開發中,Tomcat 是最常用的 Servlet 容器,而項目類型通常分為 Maven 管理(依賴自動處理、多模塊聚合) 和 非 Maven 純手工管理(手動引入 jar 包、配置項目結構)。本文覆蓋 兩種項目類型 的 T…

使用 React Native Web 實現三端統一開發

使用 React Native Web 實現三端統一開發 關鍵點 React Native Web 簡介:React Native Web 是一個允許開發者使用 React Native 組件和 API 構建 Web 應用的庫,支持在 iOS、Android 和 Web 上使用同一套代碼。架構:通過 React DOM 渲染 Rea…

分享一個git上基于std::array實現的循環隊列(Cycle Queue)模板類庫

為充分利用向量空間,克服“假溢出”現象的方法是:將向量空間想象為一個首尾相接的圓環,并稱這種向量為循環向量。存儲在其中的隊列稱為循環隊列(Circular Queue)。循環隊列是把順序隊列首尾相連,把存儲隊列元素的表從邏輯上看成一個環,成為循環隊列。 網上有很多關于循…

三維視頻融合平臺:如何構建動態感知的數字空間

分享大綱: 你的三維平臺為何不能承載動態視頻捷碼打造三維視頻融合平臺的三步法則為何選擇捷碼 在智慧城市建設過程中,將實時視頻與三維空間結合,已經成為一種主流趨勢。傳統視頻監控模式,經常面臨視頻分散、操作復雜等問題。然而…

【AI Study】第五天,Matplotlib(5)- 顏色映射

文章概要 本文詳細介紹 Matplotlib 的顏色映射功能,包括: 顏色映射類型顏色映射設置數據標準化顏色條 顏色映射類型 pcolormesh import matplotlib.pyplot as plt import numpy as np# 創建網格數據 x np.linspace(-3, 3, 100) y np.linspace(-3,…

DB2中合理使用INCLUDE關鍵字創建索引

DB2中合理使用 INCLUDE 關鍵字創建索引 1. 為何還需要 INCLUDE?——從索引的兩大痛點說起 查詢想“只讀索引不回表”,卻又不想把列都做鍵 → 聯合索引空間膨脹,更新放大。唯一索引定位快,但只能返回鍵列數據 → 仍需 I/O 跳回數據…

基于Spring Boot的民宿管理系統設計與實現

目錄 一.🦁前言二.🦁開源代碼與組件使用情況說明三.🦁核心功能1. ?算法設計2. ?Spring Boot框架3. ?Vue.js框架4. ?部署項目 四.🦁演示效果1. 管理員模塊1.1 瀏覽后臺首頁1.2 預訂信息管理1.3 入住信息管理1.4 退房信息管理1.…

大數據系統架構實踐(一):Zookeeper集群部署

大數據系統架構實踐(一):Zookeeper集群部署 文章目錄 大數據系統架構實踐(一):Zookeeper集群部署一、Zookeeper簡介二、部署前準備三、部署Zookeeper集群1. 下載并解壓安裝包2. 配置zoo.cfg3. 設置日志目錄…

《道德經》:探尋古老智慧中的哲學之光

我強烈推薦4本可以改變命運的經典著作: 《壽康寶鑒》在線閱讀白話文《欲海回狂》在線閱讀白話文《陰律無情》在線閱讀白話文《了凡四訓》在線閱讀白話文 《道德經》作為道家經典,短短五千言,卻字字珠璣,蘊含著超越時空的哲學智慧。…

科技賦能民生:中建海龍為民生改善注入新動力

在社會發展的進程中,民生改善始終占據著核心地位。住房、基礎設施建設等民生領域的進步,直接關系到民眾的生活質量與幸福感。中建海龍科技有限公司(以下簡稱“中建海龍”)作為建筑行業的創新引領者,憑借其強大的科技實…

BI 賦能,打造數據可視化看板新體驗

BI 賦能,打造數據可視化看板新體驗 引言 在當今數字化時代,數據成為企業決策的重要依據。如何從海量的數據中提取有價值的信息,并以直觀、易懂的方式呈現出來,是企業面臨的重要挑戰。商業智能(BI)工具的出…

vue2設置自定義域名跳轉

需求:首次登錄域名為aa.com,之后登錄系統后在系統內某個模塊設置三級域名為second,之后退出登錄到aa.com,登錄進入系統后域名自動變為second.aa.com,最后退出的域名也是second.aa.com,通過不同的域名配置動態的登錄頁面…

“地標界愛馬仕”再拓疆域:世酒中菜聯袂赤水金釵石斛定義中國GI

“地標界愛馬仕”再拓疆域:世酒中菜聯袂赤水金釵石斛,定義中國GI奢侈品新高度 ——中世國際與貴州斛滿多戰略合作簽約儀式在赤水舉行 赤水市,2025年5月18日——被譽為“地標界愛馬仕”的頂級奢侈品牌世酒中菜 (世界酒中國菜全球…

零基礎、大白話,Vue3全篇通俗療法(上):基礎知識【看得懂】

前言 最近有個小朋友想了解Vue前端技術,但他只懂一些HTML基礎,讓我用最簡單的方式講解。于是就有了這篇面向初學者的博文。 老手請繞行,本文專為新手準備。如果發現用詞不當的地方歡迎留言指正,覺得對新手有幫助的話請收藏點贊。 …

JavaScript性能優化實戰

JavaScript性能優化實戰技術文章大綱 性能優化的重要性 解釋為什么性能優化對用戶體驗和業務指標至關重要討論核心Web指標(LCP、FID、CLS)與JavaScript性能的關系 代碼層面優化 減少DOM操作,使用文檔片段或虛擬DOM避免頻繁的重繪和回流&a…

考研英語作文評分標準專業批改

考研英語作文專業批改經過官方評分標準嚴格對標,徹底改變你的作文提升方式,打開 懂試帝小程序 直達批改。 🎯 批改服務核心優勢 ? 官方標準嚴格對標 完全按照考研英語官方五檔評分制,從內容完整性、組織連貫性、語言多樣性到語…

智能群躍小助手發布說明

1.初次登陸需要授權碼 2.社群維護頁面 3.產品營銷頁面