Redis 延遲雙刪的實現(xiàn)示例
延遲雙刪(Delayed Double Deletion) 是在 Cache-Aside 基礎上,為了解決"并發(fā)讀寫導致緩存回填舊值"問題而設計的方案。
一、問題背景:為什么需要雙刪?
先看單刪的問題場景(先刪緩存,再更新DB):
時間點 線程A(寫) 線程B(讀)
t1 刪除緩存
t2 查詢緩存(未命中)
t3 查詢數(shù)據(jù)庫 → 得到舊值
t4 更新數(shù)據(jù)庫為新值
t5 將舊值寫入緩存 ← 緩存變臟!
即使你先更新DB再刪緩存,也有類似風險:
時間點 線程A(寫) 線程B(讀)
t1 更新數(shù)據(jù)庫
t2 查詢數(shù)據(jù)庫 → 得到舊值(因主從延遲等)
t3 刪除緩存
t4 將舊值寫入緩存 ← 緩存變臟!
延遲雙刪的核心思想:等一等,讓并發(fā)的讀請求都結束了,再把緩存清掉。
二、延遲雙刪的具體步驟
1. 先刪除緩存
2. 更新數(shù)據(jù)庫
3. 休眠/等待一段時間(比如 200ms~1s)
4. 再次刪除緩存
用代碼表示:
import time
def update_with_delayed_double_deletion(key, new_value):
# 第一次刪緩存
redis.delete(key)
# 更新數(shù)據(jù)庫
db.update(key, new_value)
# 延遲一段時間(關鍵!)
time.sleep(0.5) # 500ms,根據(jù)業(yè)務調整
# 第二次刪緩存(把可能回填的舊值清掉)
redis.delete(key)三、延遲時間怎么定?
這是最關鍵的參數(shù),定太短沒效果,定太長影響性能。
建議公式:
延遲時間 ≈ 主從同步延遲 + 業(yè)務讀操作耗時 + 冗余緩沖
- 主從同步延遲:如果有主從架構,通常 100ms~500ms
- 業(yè)務讀操作耗時:查詢DB + 序列化 + 網絡往返
- 冗余緩沖:再加 100~200ms 保險
實際建議:
- 無主從:100~300ms
- 有主從:300~800ms
- 高并發(fā)場景:可以動態(tài)調整,或根據(jù)監(jiān)控數(shù)據(jù)優(yōu)化
四、第二次刪除失敗怎么辦?
如果第二次刪緩存時 Redis 掛了或網絡抖動,緩存還是會臟。
解決方案:引入異步重試
import threading
def update_with_retry(key, new_value):
# 第一次刪 + 更新DB
redis.delete(key)
db.update(key, new_value)
# 延遲后異步執(zhí)行第二次刪除
def delayed_delete():
time.sleep(0.5)
try:
redis.delete(key)
except Exception:
# 失敗則放入重試隊列(MQ 或本地延遲隊列)
retry_queue.put(key)
threading.Thread(target=delayed_delete).start()更生產化的做法是用 消息隊列 或 延遲任務框架(如 Celery、XXL-Job)來做第二次刪除,確保可靠執(zhí)行。
五、完整流程圖
寫請求到來
│
▼
┌─────────────┐
│ 刪除緩存 │?── 第一次刪除,清掉舊值
└─────────────┘
│
▼
┌─────────────┐
│ 更新數(shù)據(jù)庫 │
└─────────────┘
│
▼
┌─────────────┐
│ 延遲等待 │?── 等并發(fā)讀請求結束,舊值回填完成
└─────────────┘
│
▼
┌─────────────┐
│ 再次刪除緩存 │?── 第二次刪除,清掉可能回填的舊值
│ (帶重試) │
└─────────────┘
│
▼
結束
六、優(yōu)缺點總結
| 優(yōu)點 | 缺點 |
|---|---|
| 實現(xiàn)簡單,不引入額外組件 | 延遲等待會阻塞寫請求(或用異步) |
| 能有效降低緩存不一致概率 | 延遲時間不好精確估算 |
| 兼容現(xiàn)有 Cache-Aside 架構 | 極端高并發(fā)下仍可能有小概率不一致 |
七、適用場景
- 讀多寫少:寫操作不頻繁,延遲等待的開銷可接受
- 允許秒級最終一致:不要求實時強一致
- 無主從或主從延遲可控:延遲時間能估算得準
八、一句話總結
延遲雙刪 = "先刪緩存 → 更新DB → 等一會兒 → 再刪一次",用"等一等"來覆蓋并發(fā)讀回填舊值的時間窗口。
到此這篇關于Redis 延遲雙刪的實現(xiàn)示例的文章就介紹到這了,更多相關Redis 延遲雙刪內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Redis實現(xiàn)每日簽到功能(大數(shù)據(jù)量)
在面對百萬級用戶簽到情況下,傳統(tǒng)數(shù)據(jù)庫存儲和判斷會遇到瓶頸,使用Redis的二進制數(shù)據(jù)類型可實現(xiàn)高效的簽到功能,示例代碼展示了如何調用這些功能,包括當天簽到、補簽以及查詢簽到記錄,PHP結合Redis二進制數(shù)據(jù)類型可有效處理大數(shù)據(jù)量下的簽到問題2024-10-10
redis批量刪除namespace下的數(shù)據(jù)的實現(xiàn)步驟
在開發(fā)中為了更好的管理數(shù)據(jù),對redis進行了分組存儲操作,在存值時加了命名空間來實現(xiàn),本文就來介紹一下redis批量刪除namespace下的數(shù)據(jù)的實現(xiàn)步驟,感興趣的可以了解一下2025-12-12
Redis分布式鎖升級版RedLock及SpringBoot實現(xiàn)方法
這篇文章主要介紹了Redis分布式鎖升級版RedLock及SpringBoot實現(xiàn),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02

