以下內容面向高併發業務與雲邊協同場景,聚焦“可落地、可度量、可擴展”。如無特別説明,示例基於 redis-cli 或常見客户端實現。🚀
場景—能力—風險對照表(落地速覽)
| 場景 | 核心結構/命令 | 設計要點 | 典型指標/目標 | 風險與邊界 |
|---|---|---|---|---|
| 旁路緩存(讀多寫少) | GET / SETEX |
<span style="color:red">TTL</span> 分層、熱點預熱、失效回填 | P95 延遲降低、緩存命中率 ≥ <span style="color:red">90%</span> | <span style="color:red">雪崩/擊穿/穿透</span> |
| 防緩存穿透 | RedisBloom BF.ADD/EXISTS |
先判存在性再查庫 | 降低空擊 ≥ <span style="color:red">95%</span> | 需加載模塊、假陽性可接受 |
| 熱點Key治理 | <span style="color:red">本地緩存</span> + Redis、讀寫隔離 | 多級緩存、<span style="color:red">隨機TTL</span> | 降峯 | 版本一致性 |
| 分佈式鎖 | SET key val NX PX + Lua 釋放 |
<span style="color:red">唯一值</span>+過期+原子釋放 | 單資源互斥 | 時鐘漂移、鎖失效 |
| 限流/風控 | INCR + 過期 / Lua / Redis Functions |
固定/滑動/令牌桶 | 穩住 QPS、<span style="color:red">熔斷</span>保護 | 維度爆炸 |
| 排行榜/Feed | ZADD/ZREVRANGE |
<span style="color:red">Sorted Set</span> 按分數排序 | T+實時榜單 | N 大時內存佔用 |
| 事件流隊列 | <span style="color:red">Streams</span> XADD/XREADGROUP |
消費組、ACK、死信 | 消息有序/可回溯 | 消費堆積處理 |
| 會話/鑑權 | SETEX/HSET |
輕會話、黑名單 | 登出實時生效 | 跨端一致 |
| 計數與UV | HINCRBY / <span style="color:red">HyperLogLog</span> |
精確/近似並存 | UV 誤差可控 | 近似誤差容忍 |
| 地理/就近調度 | GEOADD/GEORADIUS |
LBS 場景、<span style="color:red">就近</span>訪問 | 距離查詢 | 半徑/精度限制 |
關鍵方案與代碼(含解釋)
1) 旁路緩存(Cache-Aside)與熱點保護 ⚡
# 讀:查緩存 → 未命中查庫 → 回填並設置隨機TTL,降低同時失效
GET product:123
# 未命中後回填
SETEX product:123 $((600 + RANDOM%120)) "json-payload"
解釋:SETEX 直接設置值與 TTL,加入<span style="color:red">隨機 TTL</span>避免同刻同時過期導致<span style="color:red">雪崩</span>。回填數據建議攜帶版本號或 ETag,便於灰度與回滾。
工作流(vditor/mermaid 支持):
2) 分佈式鎖(互斥與冪等)🔒
# 加鎖:確保唯一值 + 過期時間(毫秒)
SET lock:order:987 "uuid-xyz" NX PX 10000
# 釋放:僅持有者可刪,Lua 保證原子性
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else return 0 end" 1 lock:order:987 uuid-xyz
解釋:用 SET NX PX 獲取鎖,值為<span style="color:red">唯一標識</span>,防止誤刪他人鎖;釋放用 Lua 比較再刪,確保<span style="color:red">原子</span>。對跨機房強一致鎖,需評估 RedLock 的容錯假設與時鐘風險,關鍵路徑更宜用隊列串行化或單點協調。
3) 固定窗口限流(簡單可依賴)🛡️
# 以用户ID為維度,1分鐘最多100次
local key = "rl:"..ARGV[1]..":"..(math.floor(redis.call('TIME')[1]/60))
local cur = redis.call('INCR', key)
if cur == 1 then redis.call('EXPIRE', key, 60) end
return cur
解釋:按<span style="color:red">固定窗口</span>聚合,首次 INCR 時設置 60s 過期,返回計數;超過閾值在業務側拒絕或降級。對“邊界抖動”可升級至<span style="color:red">滑動窗口或令牌桶</span>(Lua/Redis Functions 持久化腳本庫,便於版本管理)。
速算公式:若閾值R,窗口T秒,則理論上限 QPS ≈ <span style="color:red">R/T</span>。滑動窗口、令牌桶能平滑瞬時峯值。
4) 排行榜/計分板(Sorted Set)📈
# 增加積分併入榜
ZINCRBY rank:season1 30 user:42
# 取前10名
ZREVRANGE rank:season1 0 9 WITHSCORES
解釋:Sorted Set 以分數排序,適用於分數可變、需要快速 TopN 的場景;大榜建議分片(按前綴或區間)並定期<span style="color:red">壓縮/歸檔</span>,避免內存膨脹。
5) 事件流/異步解耦(Redis Streams)🧠
# 生產消息
XADD stream:order * orderId 987 status created
# 創建消費組
XGROUP CREATE stream:order cgrp0 $ MKSTREAM
# 消費(從組內)
XREADGROUP GROUP cgrp0 c1 COUNT 10 BLOCK 2000 STREAMS stream:order >
# 處理成功後確認
XACK stream:order cgrp0 <message-id>
解釋:Streams 提供<span style="color:red">消費組</span>與待處理隊列,支持“<span style="color:red">至少一次</span>”投遞與回溯。需監控 <span style="color:red">PEL</span>(未確認條目)並設計重試/死信隊列。
6) 防穿透(RedisBloom,需模塊)🧪
# 初始化過濾器(只需一次)
BF.RESERVE bf:user 0.01 1000000
# 寫入/檢查
BF.ADD bf:user u:123
BF.EXISTS bf:user u:123
解釋:布隆過濾器以<span style="color:red">極低內存</span>換取近似存在判斷,0.01 表示目標假陽性率。適合“先判存在再查庫”以降低<span style="color:red">空擊</span>與下游壓力。
選型與治理要點(務實結論)
- 優先級:讀多寫少優先上緩存,寫多讀多評估一致性成本;跨域事務慎用鎖,儘量改造為冪等+異步。
- 穩定性:必做<span style="color:red">限流、熔斷、降級</span>三件套;TTL 隨機化、預熱、批量回填,避免集中抖動。
- 成本:Key 設計短小、結構緊湊;超大對象分片/壓縮;冷數據落盤或外置存儲(例如對象存儲)。
- 觀測:埋點 <span style="color:red">命中率/慢查詢/內存碎片/大Key</span>;自動巡檢與告警閾值分級。
- 前瞻:充分利用 <span style="color:red">Redis Functions</span>(持久化腳本庫)沉澱限流、冪等、記分等原語,做到“平台化複用”。
小結(面向業務的判斷標準)✅
當你的目標是 極低延遲、強韌性、彈性削峯,Redis 是“第一梯隊”組件;當你的訴求偏向 強一致長事務、超大對象、複雜聚合,應轉向數據庫/搜索/消息總線等更合適的系統,再由 Redis 做“前排加速層”。
堅持一個原則:把<span style="color:red">簡單正確</span>做成平台能力,把<span style="color:red">複雜偶發</span>隔離在邊緣流程。這樣,性能與可用性都會穩穩落地。✨