緩存擊穿中邏輯過期和單純互斥鎖的區(qū)別及說明
一、邏輯過期中加互斥鎖的核心原因
邏輯過期的核心是 “過期不刪緩存,返回舊數(shù)據(jù)”,但如果不加互斥鎖,會(huì)出現(xiàn)一個(gè)關(guān)鍵問題:當(dāng)緩存邏輯過期后,所有請(qǐng)求都會(huì)觸發(fā) “更新緩存” 的邏輯—— 哪怕你用了異步線程,也會(huì)導(dǎo)致大量異步任務(wù)同時(shí)去查數(shù)據(jù)庫、更新緩存,相當(dāng)于把 “緩存擊穿” 的壓力從 “同步請(qǐng)求打數(shù)據(jù)庫” 變成了 “異步線程打數(shù)據(jù)庫”,數(shù)據(jù)庫依然會(huì)被瞬間壓垮。
舉個(gè)具體例子:
- 秒殺商品的緩存邏輯過期了,瞬間有 1000 個(gè)請(qǐng)求進(jìn)來;
- 如果不加鎖:這 1000 個(gè)請(qǐng)求都會(huì)觸發(fā)異步更新,1000 個(gè)線程同時(shí)查數(shù)據(jù)庫的商品庫存,數(shù)據(jù)庫直接扛不??;
- 如果加鎖:只有 1 個(gè)請(qǐng)求能拿到鎖,觸發(fā) 1 次異步更新,剩下 999 個(gè)請(qǐng)求直接返回舊數(shù)據(jù),數(shù)據(jù)庫只承受 1 次查詢壓力。
所以,邏輯過期里的互斥鎖,目的是限制 “更新緩存” 的操作只能有一個(gè)請(qǐng)求執(zhí)行,徹底杜絕數(shù)據(jù)庫被大量更新請(qǐng)求沖擊,這是邏輯過期方案能防擊穿的 “最后一道保障”。
二、邏輯過期(加鎖) vs 單純互斥鎖(防緩存擊穿)的核心區(qū)別
先明確 “單純用互斥鎖防緩存擊穿” 的常規(guī)邏輯:
緩存物理過期(Redis 自動(dòng)刪)→ 請(qǐng)求進(jìn)來發(fā)現(xiàn)緩存空 → 搶鎖 → 搶到鎖的查數(shù)據(jù)庫、更新緩存 → 沒搶到鎖的等待 / 重試 → 最終拿到新緩存數(shù)據(jù)。
兩種方案的核心差異可以用表格清晰對(duì)比:
| 維度 | 邏輯過期 + 互斥鎖 | 單純互斥鎖(物理過期) |
|---|---|---|
| 緩存是否被刪除 | 物理永不過期(只判斷邏輯過期時(shí)間) | 物理過期(Redis 自動(dòng)刪除緩存) |
| 過期后請(qǐng)求的返回值 | 直接返回舊數(shù)據(jù)(不阻塞) | 沒搶到鎖的請(qǐng)求會(huì)等待 / 重試(阻塞) |
| 數(shù)據(jù)一致性 | 短暫返回舊數(shù)據(jù)(最終會(huì)更新) | 拿到的都是最新數(shù)據(jù)(無臟數(shù)據(jù)) |
| 接口響應(yīng)速度 | 極快(無論是否過期,都快速返回) | 過期瞬間的請(qǐng)求會(huì)有等待(響應(yīng)慢) |
| 適用場(chǎng)景 | 熱點(diǎn) key、對(duì)實(shí)時(shí)性要求低、追求高可用(如首頁) | 數(shù)據(jù)實(shí)時(shí)性要求高、可接受 |
三、兩種方案的執(zhí)行流程對(duì)比(更直觀)
1. 單純互斥鎖(物理過期)的執(zhí)行流程

核心問題:緩存過期后,所有請(qǐng)求都要等鎖釋放,會(huì)出現(xiàn)請(qǐng)求堆積、接口響應(yīng)慢的情況。
2. 邏輯過期 + 互斥鎖的執(zhí)行流程

- 核心優(yōu)勢(shì):無論是否搶到鎖,都立刻返回舊數(shù)據(jù),接口無阻塞,只有 1 個(gè)異步線程去更新緩存。
四、關(guān)鍵補(bǔ)充:兩種方案的 “鎖” 作用不同
- 單純互斥鎖:鎖的是 “查數(shù)據(jù)庫的權(quán)限”—— 因?yàn)榫彺婵樟?,必須保證只有一個(gè)請(qǐng)求查庫,否則就擊穿;
- 邏輯過期 + 互斥鎖:鎖的是 “更新緩存的權(quán)限”—— 緩存還在(有舊數(shù)據(jù)),只是要更新,保證只有一個(gè)請(qǐng)求去更新,其他請(qǐng)求先用舊數(shù)據(jù)。
總結(jié)
- 邏輯過期加互斥鎖,是為了防止緩存過期后大量請(qǐng)求同時(shí)觸發(fā)緩存更新,避免數(shù)據(jù)庫被異步更新請(qǐng)求壓垮;
- 和單純互斥鎖的核心區(qū)別:邏輯過期方案不刪除緩存、返回舊數(shù)據(jù)、無請(qǐng)求阻塞,而單純互斥鎖會(huì)刪除緩存、等待鎖釋放、返回最新數(shù)據(jù);
- 選型原則:對(duì)實(shí)時(shí)性要求低、追求高并發(fā)高可用選 “邏輯過期 + 鎖”,對(duì)實(shí)時(shí)性要求高選 “單純互斥鎖”。
通俗解釋二者區(qū)別
單純的互斥鎖的話只要緩存過期相當(dāng)于就在redis里面被刪除了,然后請(qǐng)求到redis發(fā)現(xiàn)沒緩存,然后就拿到互斥鎖去數(shù)據(jù)庫里面更新緩存是吧,其他線程就等待拿到互斥鎖的那個(gè)線程更新緩存完后才查到redis的緩存并且返回,然后其他線程拿不到鎖就會(huì)一直重試或者直接寫相關(guān)代碼友好返回暫無數(shù)據(jù),但是這個(gè)可以保證緩存和數(shù)據(jù)庫完全一致;
然后邏輯過期就是,放到緩存里面不設(shè)置過期時(shí)間,但是有一個(gè)邏輯過期字段,然后由于沒有實(shí)際過期時(shí)間,redis里面這個(gè)數(shù)據(jù)永久存在,然后就判斷是否邏輯過期而已,然后如果過期了也是其中一個(gè)拿互斥鎖去更新緩存,但是其余所有線程就先返回已經(jīng)邏輯過期的緩存而已,就不會(huì)耽擱其他線程,但是不能保證緩存和數(shù)據(jù)庫的一致性。
單純互斥鎖方案不強(qiáng)制要求提前預(yù)熱緩存數(shù)據(jù),哪怕沒緩存就會(huì)去數(shù)據(jù)庫查詢;但是邏輯過期必須要先提前預(yù)熱緩存數(shù)據(jù),邏輯過期的核心是 “緩存始終有數(shù)據(jù),哪怕是舊數(shù)據(jù)”,如果不預(yù)熱那么就體現(xiàn)不出邏輯過期方案的作用出來
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解讀Redis秒殺優(yōu)化方案(阻塞隊(duì)列+基于Stream流的消息隊(duì)列)
該文章介紹了使用Redis的阻塞隊(duì)列和Stream流的消息隊(duì)列來優(yōu)化秒殺系統(tǒng)的方案,通過將秒殺流程拆分為兩條流水線,使用Redis緩存緩解數(shù)據(jù)庫壓力,并結(jié)合Lua腳本進(jìn)行原子性判斷,使用阻塞隊(duì)列和消息隊(duì)列異步處理訂單,有效提高了系統(tǒng)的并發(fā)處理能力和可用性2025-02-02
redis由于目標(biāo)計(jì)算機(jī)積極拒絕,無法連接的解決
這篇文章主要介紹了redis由于目標(biāo)計(jì)算機(jī)積極拒絕,無法連接的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
詳解Redis中的BigKey如何發(fā)現(xiàn)和處理
這篇文章主要為大家詳細(xì)介紹了Redis中的BigKey如何發(fā)現(xiàn)和處理,文中給大家詳細(xì)講解了BigKey危害和如何解決這些問題,文章通過代碼示例和圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
Redis 實(shí)現(xiàn)消息隊(duì)列實(shí)際案例
文章探討Redis作為消息隊(duì)列的三大核心方案(List、Pub/Sub、Stream)及適用場(chǎng)景,分析了輕量部署、高性能、多語言支持等優(yōu)勢(shì),指出Stream在可靠性、消息確認(rèn)、死信隊(duì)列等企業(yè)級(jí)需求上表現(xiàn)最佳,適合電商等高吞吐場(chǎng)景,并提供了實(shí)際應(yīng)用案例與優(yōu)化建議,感興趣的朋友一起看看吧2025-09-09
redis執(zhí)行l(wèi)ua腳本的實(shí)現(xiàn)
本文主要介紹了redis執(zhí)行l(wèi)ua腳本的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10

