Redis常見的 使用場景:
- 緩存系統(核心場景)
- 存儲熱點數據,減少數據庫訪問壓力。提升接口響應速度。
- 技術點:
- 用String/Hash 存儲結構化數據
- 結合過期時間(TTL)和緩存淘汰策略(如LRU)管理內存。
- 解決緩存問題:穿透(布隆過濾器)、擊穿(互斥鎖)、雪崩(隨機過期時間)。
- 計數器與限流
- 實時統計高頻變動的值,或限制接口訪問訪問頻率。
- 技術點:
- 用String存儲單計數器(INCR )。
- 用HASH存儲多維計數器(HINCRBY user:100 stats:likes 1)
- 限流可結合Expire自動重置技術(如 INCR limit:ip:192.168.1.1 + EXPIRE … 60)。
- 消息隊列
- 實現簡單的異步通信,解耦生產者和消費者。
- 技術點:
- 用List模擬隊列:LPUSH(生產)+ RPOP(消費),或阻塞版本BRPOP避免空輪詢。
- 缺點:無消息確認機制,需要結合確認機制,需結合AOF持久化減少丟失風險;高級需求(如延時隊列)需要額外設計。
- 排行榜與實時排名
- 作用:根據分數動態排序,商品銷量榜,用戶貢獻榜。
- 技術點:
- 用Sorted Set存儲:ZADD rank:game user:100 95(用戶 100 分數 95),ZRANGE rank:game 0 9 WITHSCORES 取前 10 名。
- 支持分數自增(ZINCRBY),適合動態更新排名。
- 分布式鎖
- 作用:在分布式系統中保證臨界資源的互斥訪問(如庫存扣減、訂單創建)
- 優化:使用Redisson框架,支持自動續期、公平鎖、可重入等高級特性。
- 用戶行為分析
- 記錄用戶行為狀態,快速統計群體特征。
- 技術點:
- 用BitMap存儲每日登錄狀態:SETBIT login:20201001 user:100 1(用戶100在20201001登錄)通過BITOP作位運算統計活躍用戶。
- 用SET存儲用戶標簽:SADD tag:view:goods100 :100,通過交集(SINTER)找共同標簽用戶。
- 地理信息服務
- 作用:存儲地理位置,實現附近搜索,距離計算等功能;
- 技術點:
- 用Geospatial命令:GEOADD shops 116.40 39.90 shop:1 存儲經緯度,GEORADIUS shops 116.40 39.90 5 km 查找 5 公里內的商家。
- 會話存儲
- 作用:存儲用戶登錄狀態(如Session、Token),支持分布式系統共享會話。
- 技術點:
- 用String存儲Session/Token:SET session:user100 ”xxx“EX 7200(2小時過期)。
- 結合EXPIRE自動銷毀過期會話,減輕服務器存儲壓力。
緩存場景
緩存關鍵問題:數據一致性、可用性、內存效率。同時規避緩存常見風險(如穿透、擊穿、雪崩)。
-
緩存穿透:避免”不存在的數據“,穿透到數據庫。
問題本質:請求查詢 不存在的數據,導致緩存無法命中。所有請求都直接打到數據庫,導致數據庫壓力驟增。
解決方案:- 空值緩存:數據庫給查詢為空時,可以將空值存入緩存。并設置較短的過期時間。避免重復穿透。 惡意攻擊會導致內存膨脹。
- 布隆過濾器:在緩存前加一層布隆過濾器,將數據庫中存在的key提前存入過濾器,請求先過過濾器。
- 參數校驗:接口層直接攔截非法參數(如id<0,非預期格式的key),從源頭阻斷無效請求。
-
緩存擊穿:避免熱點key過期,導致數據庫瞬間過載。
- 問題本質:某個高頻訪問的熱點key過期瞬間大量請求同時命中失效的緩存,全部穿透到數據庫,造成數據庫“瞬間峰值”。
- 解決方式:
- 互斥鎖(分布式鎖):緩存未命中時,只有一個請求能獲取鎖并查詢數據庫,其他請求自選等待(或直接返回默認值),避免“并發穿透。注意:鎖過期時間需要大于數據庫查詢時間,防止鎖提前釋放導致并發問題;同時注意避免死鎖。
- 熱點key永不過期
- 業務層不設置TTL,通過后臺定時任務(如Cron腳本主動更新(如每小時更新商品信息)。
- 若數據需要實時更新,殼子啊數據變更時主動SET命令覆蓋緩存,而非TTL過期。
- 過期時間錯開:對同類熱點key設置隨機過期時間(如基礎過期時間+5~8分鐘隨機值)。
-
緩存雪崩問題,避免大量key集體過期/集群宕機導致數據庫崩潰
問題本質:
同一時間段內大量緩存key集中過期,請求全部穿透到數據庫。
Redis緩存集群整體宕機,緩存層整體失效。所有請求直接打向數據庫。
解決方法:- 針對大量key同時過期:給每個key設置隨機過期時間。分散過期時間。
- 針對集群宕機:
- 緩存使用集群高可用
- 多級緩存:在Redis之前使用本地緩存(如:Caffeine、GuavaCache),即使Redis宕機本地緩存也可以暫代部分請求,減輕數據庫壓力。
- 熔斷降級:通過監控工具(如Prometheus+Grafana)實時檢測數據庫壓力。當壓力超過指定閾值時,出發熔斷(直接返回默認值或錯誤提示),避免數據庫崩潰。
- 流量控制:結合網關做接口限流,限制單位時間內的請求量。
數據一致性
緩存與數據庫 盡量保持一致,避免緩存存舊數據,數據庫存新數據 的矛盾場景。
- 選擇合適的 更新策略:
- 處理緩存更新失敗問題:
- 若數據庫更新成功,但刪除緩存失敗,會導致緩存殘留舊數據。解決方案:
- 重試機制:刪除緩存失敗后,通過 本地重試機制或消息隊列 異步重試(如將”刪除緩存任務存入隊列中,失敗后重新消費),確保緩存最終被刪除。
- 版本號+時間戳:緩存中存儲“數據+版本號”,查詢時對比數據庫版本號,若緩存版本低則主動更新。
- 若數據庫更新成功,但刪除緩存失敗,會導致緩存殘留舊數據。解決方案:
相關優化
Redis是內存數據庫,需合理管理內存,避免內存溢出 性能下降。
- 緩存key的設計:
- 簡潔且唯一:用“業務前綴+唯一標識”格式(如user:session:1001、goods:detail:abc123)避免key沖突
- 避免過長:key過長會增加內存占用。
- 避免大量小key,大量零散的小key會浪費內存(如 user💯name、user💯age)建議使用Hash合并(如 user:100 {name: “xxx”, age: 20})。
- 合理配置淘汰策略:當Redis內存到達maxmemory閾值時,需通過淘汰策略釋放內存,避免OOM內存溢出。需根據業務選擇策略:
- 核心策略推薦:
- LRU:淘汰 最近最少使用的key(適合熱點數據場景,如商品詳情),對應配置 maxmemory-policy allkeys-lru(所有 key 中選 LRU)或 volatile-lru(只在設置了 TTL 的 key 中選 LRU)。
- LFU:淘汰最近訪問頻率最低的key(適合長期低頻訪問數據,如歷史訂單)。對應配置:allkey-lfu或volatile-lfu。
- 避免使用的策略:
- noeviction(默認):內存滿時,直接拒絕寫請求,會導致業務報錯,除非是只讀場景。
- random:隨即淘汰,可能淘汰熱點數據,不推薦。
- 核心策略推薦:
- 控制緩存粒度與過期時間。
- 緩存粒度不宜過粗過細:
- 過粗:導致緩存數據冗余,更新世需全量替換,浪費帶寬和內存。
- 過細:將對象每個屬性單獨存儲,導致 key數量增加,和查詢次數增多。
- 建議:按“業務查詢維度”設計粒度,緩存對象采用聚合數據。
- 過期時間合適
- 緩存粒度不宜過粗過細:
監控與運維
- 核心指標:需要實時監控Redis的緩存命中率(目標>=95%),內存使用率、key過期數量、數據庫訪問量等。當指標異常時(如命中率驟降、內存超閾值) 及時告警。
- 工具推薦:Prometheus+Grafana、Redis Insight。
- 持久化配置:若緩存數據需要重啟后恢復(如熱點商品緩存),需要開啟AOF和RDB持久化‘
- 優先使用AOF+RDB混合持久化。AOF保證數據不丟失(每秒刷盤),RDB用于數據快速恢復。
- 若緩存數據可重建(如數據庫重新加載),可關閉持久化,減少IO操作。