日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

Redis缓存穿透、击穿、雪崩、预热、更新、降级

發(fā)布時(shí)間:2025/3/15 数据库 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis缓存穿透、击穿、雪崩、预热、更新、降级 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Redis是高性能的分布式內(nèi)存數(shù)據(jù)庫(kù),對(duì)于內(nèi)存數(shù)據(jù)庫(kù)經(jīng)常會(huì)出現(xiàn)下面幾種情況,也經(jīng)常會(huì)出現(xiàn)在Redis面試題中:緩存穿透、緩存擊穿、緩存雪崩、緩存預(yù)熱、緩存更新、緩存降級(jí)。本篇分別介紹這些概念以及對(duì)應(yīng)的解決方案。

一、緩存穿透

當(dāng)查詢Redis中沒(méi)有的數(shù)據(jù)時(shí),該查詢會(huì)下沉到數(shù)據(jù)庫(kù)層,同時(shí)數(shù)據(jù)庫(kù)層也沒(méi)有該數(shù)據(jù),當(dāng)這種情況大量出現(xiàn)或被惡意攻擊時(shí),接口的訪問(wèn)全部透過(guò)Redis訪問(wèn)數(shù)據(jù)庫(kù),而數(shù)據(jù)庫(kù)中也沒(méi)有這些數(shù)據(jù),我們稱這種現(xiàn)象為"緩存穿透"。緩存穿透會(huì)穿透Redis的保護(hù),提升底層數(shù)據(jù)庫(kù)的負(fù)載壓力,同時(shí)這類穿透查詢沒(méi)有數(shù)據(jù)返回也造成了網(wǎng)絡(luò)和計(jì)算資源的浪費(fèi)。

解決方案:

  • 在接口訪問(wèn)層對(duì)用戶做校驗(yàn),如接口傳參、登陸狀態(tài)、n秒內(nèi)訪問(wèn)接口的次數(shù);
  • 利用布隆過(guò)濾器,將數(shù)據(jù)庫(kù)層有的數(shù)據(jù)key存儲(chǔ)在位數(shù)組中,以判斷訪問(wèn)的key在底層數(shù)據(jù)庫(kù)中是否存在;

第一種解決方案很好理解,這里介紹一下第二種方案,我們知道布隆過(guò)濾器可以判斷key一定不在集合內(nèi)以及key極有可能在集合內(nèi)。

基于布隆過(guò)濾器,我們可以先將數(shù)據(jù)庫(kù)中數(shù)據(jù)的key存儲(chǔ)在布隆過(guò)濾器的位數(shù)組中,每次客戶端查詢數(shù)據(jù)時(shí)先訪問(wèn)Redis:

  • 如果Redis內(nèi)不存在該數(shù)據(jù),則通過(guò)布隆過(guò)濾器判斷數(shù)據(jù)是否在底層數(shù)據(jù)庫(kù)內(nèi);
  • 如果布隆過(guò)濾器告訴我們?cè)搆ey在底層庫(kù)內(nèi)不存在,則直接返回null給客戶端即可,避免了查詢底層數(shù)據(jù)庫(kù)的動(dòng)作;
  • 如果布隆過(guò)濾器告訴我們?cè)搆ey極有可能在底層數(shù)據(jù)庫(kù)內(nèi)存在,那么將查詢下推到底層數(shù)據(jù)庫(kù)即可;
  • 布隆過(guò)濾器有誤判率,雖然不能完全避免數(shù)據(jù)穿透的現(xiàn)象,但已經(jīng)可以將99.99%的穿透查詢給屏蔽在Redis層了,極大的降低了底層數(shù)據(jù)庫(kù)的壓力,減少了資源浪費(fèi)。

    二、緩存擊穿

    緩存擊穿和緩存穿透從名詞上可能很難區(qū)分開(kāi)來(lái),它們的區(qū)別是:穿透表示底層數(shù)據(jù)庫(kù)沒(méi)有數(shù)據(jù)且緩存內(nèi)也沒(méi)有數(shù)據(jù),擊穿表示底層數(shù)據(jù)庫(kù)有數(shù)據(jù)而緩存內(nèi)沒(méi)有數(shù)據(jù)。當(dāng)熱點(diǎn)數(shù)據(jù)key從緩存內(nèi)失效時(shí),大量訪問(wèn)同時(shí)請(qǐng)求這個(gè)數(shù)據(jù),就會(huì)將查詢下沉到數(shù)據(jù)庫(kù)層,此時(shí)數(shù)據(jù)庫(kù)層的負(fù)載壓力會(huì)驟增,我們稱這種現(xiàn)象為"緩存擊穿"。

    解決方案:

    • 延長(zhǎng)熱點(diǎn)key的過(guò)期時(shí)間或者設(shè)置永不過(guò)期,如排行榜,首頁(yè)等一定會(huì)有高并發(fā)的接口;
    • 利用互斥鎖保證同一時(shí)刻只有一個(gè)客戶端可以查詢底層數(shù)據(jù)庫(kù)的這個(gè)數(shù)據(jù),一旦查到數(shù)據(jù)就緩存至Redis內(nèi),避免其他大量請(qǐng)求同時(shí)穿過(guò)Redis訪問(wèn)底層數(shù)據(jù)庫(kù);

    在使用互斥鎖的時(shí)候需要避免出現(xiàn)死鎖或者鎖過(guò)期的情況:

    • 使用前面文章介紹過(guò)的lua腳本或事務(wù)將獲取鎖和設(shè)置過(guò)期時(shí)間作為一個(gè)原子性操作(如:set kk vv nx px
      30000),以避免出現(xiàn)某個(gè)客戶端獲取鎖之后宕機(jī)導(dǎo)致的鎖不被釋放造成死鎖現(xiàn)象;
    • 另起一個(gè)線程監(jiān)控獲取鎖的線程的查詢狀態(tài),快到鎖過(guò)期時(shí)間時(shí)還沒(méi)查詢結(jié)束則延長(zhǎng)鎖的過(guò)期時(shí)間,避免多次查詢多次鎖過(guò)期造成計(jì)算資源的浪費(fèi);

    三、緩存雪崩

    緩存雪崩是緩存擊穿的"大面積"版,緩存擊穿是數(shù)據(jù)庫(kù)緩存到Redis內(nèi)的熱點(diǎn)數(shù)據(jù)失效導(dǎo)致大量并發(fā)查詢穿過(guò)redis直接擊打到底層數(shù)據(jù)庫(kù),而緩存雪崩是指Redis中大量的key幾乎同時(shí)過(guò)期,然后大量并發(fā)查詢穿過(guò)redis擊打到底層數(shù)據(jù)庫(kù)上,此時(shí)數(shù)據(jù)庫(kù)層的負(fù)載壓力會(huì)驟增,我們稱這種現(xiàn)象為"緩存雪崩"。事實(shí)上緩存雪崩相比于緩存擊穿更容易發(fā)生,對(duì)于大多數(shù)公司來(lái)講,同時(shí)超大并發(fā)量訪問(wèn)同一個(gè)過(guò)時(shí)key的場(chǎng)景的確太少見(jiàn)了,而大量key同時(shí)過(guò)期,大量用戶訪問(wèn)這些key的幾率相比緩存擊穿來(lái)說(shuō)明顯更大。

    解決方案:

    • 在可接受的時(shí)間范圍內(nèi)隨機(jī)設(shè)置key的過(guò)期時(shí)間,分散key的過(guò)期時(shí)間,以防止大量的key在同一時(shí)刻過(guò)期;
    • 對(duì)于一定要在固定時(shí)間讓key失效的場(chǎng)景(例如每日12點(diǎn)準(zhǔn)時(shí)更新所有最新排名),可以在固定的失效時(shí)間時(shí)在接口服務(wù)端設(shè)置隨機(jī)延時(shí),將請(qǐng)求的時(shí)間打散,讓一部分查詢先將數(shù)據(jù)緩存起來(lái);
    • 延長(zhǎng)熱點(diǎn)key的過(guò)期時(shí)間或者設(shè)置永不過(guò)期,這一點(diǎn)和緩存擊穿中的方案一樣;

    四、緩存預(yù)熱

    緩存預(yù)熱如字面意思,當(dāng)系統(tǒng)上線時(shí),緩存內(nèi)還沒(méi)有數(shù)據(jù),如果直接提供給用戶使用,每個(gè)請(qǐng)求都會(huì)穿過(guò)緩存去訪問(wèn)底層數(shù)據(jù)庫(kù),如果并發(fā)大的話,很有可能在上線當(dāng)天就會(huì)宕機(jī),因此我們需要在上線前先將數(shù)據(jù)庫(kù)內(nèi)的熱點(diǎn)數(shù)據(jù)緩存至Redis內(nèi)再提供出去使用,這種操作就成為"緩存預(yù)熱"。

    緩存預(yù)熱的實(shí)現(xiàn)方式有很多,比較通用的方式是寫(xiě)個(gè)批任務(wù),在啟動(dòng)項(xiàng)目時(shí)或定時(shí)去觸發(fā)將底層數(shù)據(jù)庫(kù)內(nèi)的熱點(diǎn)數(shù)據(jù)加載到緩存內(nèi)。

    五、緩存更新

    緩存服務(wù)(Redis)和數(shù)據(jù)服務(wù)(底層數(shù)據(jù)庫(kù))是相互獨(dú)立且異構(gòu)的系統(tǒng),在更新緩存或更新數(shù)據(jù)的時(shí)候無(wú)法做到原子性的同時(shí)更新兩邊的數(shù)據(jù),因此在并發(fā)讀寫(xiě)或第二步操作異常時(shí)會(huì)遇到各種數(shù)據(jù)不一致的問(wèn)題。如何解決并發(fā)場(chǎng)景下更新操作的雙寫(xiě)一致是緩存系統(tǒng)的一個(gè)重要知識(shí)點(diǎn)。

    第二步操作異常:緩存和數(shù)據(jù)的操作順序中,第二個(gè)動(dòng)作報(bào)錯(cuò)。如數(shù)據(jù)庫(kù)被更新, 此時(shí)失效緩存的時(shí)候出錯(cuò),緩存內(nèi)數(shù)據(jù)仍是舊版本;

    緩存更新的設(shè)計(jì)模式有四種:

  • Cache aside:查詢:先查緩存,緩存沒(méi)有就查數(shù)據(jù)庫(kù),然后加載至緩存內(nèi);更新:先更新數(shù)據(jù)庫(kù),然后讓緩存失效;或者先失效緩存然后更新數(shù)據(jù)庫(kù);

  • Read through:在查詢操作中更新緩存,即當(dāng)緩存失效時(shí),Cache Aside 模式是由調(diào)用方負(fù)責(zé)把數(shù)據(jù)加載入緩存,而 Read Through 則用緩存服務(wù)自己來(lái)加載;

  • Write through:在更新數(shù)據(jù)時(shí)發(fā)生。當(dāng)有數(shù)據(jù)更新的時(shí)候,如果沒(méi)有命中緩存,直接更新數(shù)據(jù)庫(kù),然后返回。如果命中了緩存,則更新緩存,然后由緩存自己更新數(shù)據(jù)庫(kù);

  • Write behind caching:俗稱write back,在更新數(shù)據(jù)的時(shí)候,只更新緩存,不更新數(shù)據(jù)庫(kù),緩存會(huì)異步地定時(shí)批量更新數(shù)據(jù)庫(kù);

  • Cache aside:

    • 為了避免在并發(fā)場(chǎng)景下,多個(gè)請(qǐng)求同時(shí)更新同一個(gè)緩存導(dǎo)致臟數(shù)據(jù),因此不能直接更新緩存而是另緩存失效。
    • 先更新數(shù)據(jù)庫(kù)后失效緩存:并發(fā)場(chǎng)景下,推薦使用延遲失效(寫(xiě)請(qǐng)求完成后給緩存設(shè)置1s過(guò)期時(shí)間),在讀請(qǐng)求緩存數(shù)據(jù)時(shí)若redis內(nèi)已有該數(shù)據(jù)(其他寫(xiě)請(qǐng)求還未結(jié)束)則不更新。當(dāng)redis內(nèi)沒(méi)有該數(shù)據(jù)的時(shí)候(其他寫(xiě)請(qǐng)求已令該緩存失效),讀請(qǐng)求才會(huì)更新redis內(nèi)的數(shù)據(jù)。這里的讀請(qǐng)求緩存數(shù)據(jù)可以加上失效時(shí)間,以防第二步操作異常導(dǎo)致的不一致情況。
    • 先失效緩存后更新數(shù)據(jù)庫(kù):并發(fā)場(chǎng)景下,推薦使用延遲失效(寫(xiě)請(qǐng)求開(kāi)始前給緩存設(shè)置1s過(guò)期時(shí)間),在寫(xiě)請(qǐng)求失效緩存時(shí)設(shè)置一個(gè)1s延遲時(shí)間,然后再去更新數(shù)據(jù)庫(kù)的數(shù)據(jù),此時(shí)其他讀請(qǐng)求仍然可以讀到緩存內(nèi)的數(shù)據(jù),當(dāng)數(shù)據(jù)庫(kù)端更新完成后,緩存內(nèi)的數(shù)據(jù)已失效,之后的讀請(qǐng)求會(huì)將數(shù)據(jù)庫(kù)端最新的數(shù)據(jù)加載至緩存內(nèi)保證緩存和數(shù)據(jù)庫(kù)端數(shù)據(jù)一致性;在這種方案下,第二步操作異常不會(huì)引起數(shù)據(jù)不一致,例如設(shè)置了緩存1s后失效,然后在更新數(shù)據(jù)庫(kù)時(shí)報(bào)錯(cuò),即使緩存失效,之后的讀請(qǐng)求仍然會(huì)把更新前的數(shù)據(jù)重新加載到緩存內(nèi)。

    推薦使用先失效緩存,后更新數(shù)據(jù)庫(kù),配合延遲失效來(lái)更新緩存的模式;

    四種緩存更新模式的優(yōu)缺點(diǎn):

    • Cache Aside:實(shí)現(xiàn)起來(lái)較簡(jiǎn)單,但需要維護(hù)兩個(gè)數(shù)據(jù)存儲(chǔ),一個(gè)是緩存(Cache),一個(gè)是數(shù)據(jù)庫(kù)(Repository);
    • Read/Write Through:只需要維護(hù)一個(gè)數(shù)據(jù)存儲(chǔ)(緩存),但是實(shí)現(xiàn)起來(lái)要復(fù)雜一些;
    • Write Behind Caching:與Read/Write Through 類似,區(qū)別是Write Behind
      Caching的數(shù)據(jù)持久化操作是異步的,但是Read/Write Through 更新模式的數(shù)據(jù)持久化操作是同步的。優(yōu)點(diǎn)是直接操作內(nèi)存速度快,多次操作可以合并持久化到數(shù)據(jù)庫(kù)。缺點(diǎn)是數(shù)據(jù)可能會(huì)丟失,例如系統(tǒng)斷電等。緩存本身就是通過(guò)犧牲強(qiáng)一致性來(lái)提高性能,因此使用緩存提升性能,就會(huì)有數(shù)據(jù)更新的延遲性。這就需要我們?cè)谠u(píng)估需求和設(shè)計(jì)階段根據(jù)實(shí)際場(chǎng)景去做權(quán)衡了。

    六、緩存降級(jí)

    緩存降級(jí)是指當(dāng)訪問(wèn)量劇增、服務(wù)出現(xiàn)問(wèn)題(如響應(yīng)時(shí)間慢或不響應(yīng))或非核心服務(wù)影響到核心流程的性能時(shí),即使是有損部分其他服務(wù),仍然需要保證主服務(wù)可用。可以將其他次要服務(wù)的數(shù)據(jù)進(jìn)行緩存降級(jí),從而提升主服務(wù)的穩(wěn)定性。降級(jí)的目的是保證核心服務(wù)可用,即使是有損的。如去年雙十一的時(shí)候淘寶購(gòu)物車無(wú)法修改地址只能使用默認(rèn)地址,這個(gè)服務(wù)就是被降級(jí)了,這里阿里保證了訂單可以正常提交和付款,但修改地址的服務(wù)可以在服務(wù)器壓力降低,并發(fā)量相對(duì)減少的時(shí)候再恢復(fù)。降級(jí)可以根據(jù)實(shí)時(shí)的監(jiān)控?cái)?shù)據(jù)進(jìn)行自動(dòng)降級(jí)也可以配置開(kāi)關(guān)人工降級(jí)。是否需要降級(jí),哪些服務(wù)需要降級(jí),在什么情況下再降級(jí),取決于大家對(duì)于系統(tǒng)功能的取舍。

    文章轉(zhuǎn)自

    總結(jié)

    以上是生活随笔為你收集整理的Redis缓存穿透、击穿、雪崩、预热、更新、降级的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。