欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis緩存問(wèn)題與緩存更新機(jī)制詳解

 更新時(shí)間:2025年01月20日 10:50:16   作者:夜夜流光相皎潔_小寧  
本文主要介紹了緩存問(wèn)題及其解決方案,包括緩存穿透、緩存擊穿、緩存雪崩等問(wèn)題的成因以及相應(yīng)的預(yù)防和解決方法,同時(shí),還詳細(xì)探討了緩存更新機(jī)制,包括不同情況下的緩存更新策略和內(nèi)存淘汰機(jī)制,并對(duì)比了它們的優(yōu)缺點(diǎn)

一、緩存問(wèn)題

1.1 緩存穿透

1.1.1 問(wèn)題來(lái)源

緩存穿透是指緩存和數(shù)據(jù)庫(kù)中都沒(méi)有的數(shù)據(jù),而用戶不斷發(fā)起請(qǐng)求。由于緩存是不命中時(shí)被動(dòng)寫(xiě)的,并且出于容錯(cuò)考慮,如果從存儲(chǔ)層查不到數(shù)據(jù)則不寫(xiě)入緩存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到存儲(chǔ)層去查詢,失去了緩存的意義。在流量大時(shí),可能DB就掛掉了,要是有人利用不存在的key頻繁攻擊我們的應(yīng)用,這就是漏洞。

1.1.2 解決方案

1.1.2.1 緩存空對(duì)象

  • 從緩存取不到的數(shù)據(jù),在數(shù)據(jù)庫(kù)中也沒(méi)有取到,這時(shí)也可以將key-value對(duì)寫(xiě)為key-null,緩存有效時(shí)間可以設(shè)置短點(diǎn),如30秒(設(shè)置太長(zhǎng)會(huì)導(dǎo)致正常情況也沒(méi)法使用)。
  • 這樣可以防止攻擊用戶反復(fù)用同一個(gè)id暴力攻擊。

1.1.2.2 使用布隆過(guò)濾器

  • 類似于一個(gè)hash set,用于快速判某個(gè)元素是否存在于集合中,其典型的應(yīng)用場(chǎng)景就是快速判斷一個(gè)key是否存在于某容器,不存在就直接返回。
  • 布隆過(guò)濾器的關(guān)鍵就在于hash算法和容器大小。

1.2 緩存擊穿

1.2.1 問(wèn)題來(lái)源

緩存擊穿是指緩存某些熱點(diǎn)數(shù)據(jù)失效(一般是緩存時(shí)間到期),這時(shí)由于并發(fā)用戶特別多,同時(shí)讀緩存沒(méi)讀到數(shù)據(jù),又同時(shí)去數(shù)據(jù)庫(kù)去取數(shù)據(jù),引起數(shù)據(jù)庫(kù)壓力瞬間增大,造成過(guò)大壓力。

1.2.2 解決方案

1.2.2.1 設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過(guò)期

可以在刷緩存時(shí),設(shè)置熱點(diǎn)數(shù)據(jù)不過(guò)期。

1.2.2.2 新增后臺(tái)定時(shí)更新緩存線程(邏輯不過(guò)期)

后臺(tái)新增一個(gè)緩存更新線程,緩存快要過(guò)期前刷新緩存時(shí)間,防止緩存失效。

1.2.2.3 使用分布式互斥鎖

可以使用Redis提供的分布式互斥鎖,保證只有一個(gè)請(qǐng)求查詢數(shù)據(jù)庫(kù)和更新緩存,其他請(qǐng)求阻塞等待緩存更新完成后在訪問(wèn)緩存。

1.2.2.4 接口限流與熔斷,降級(jí)

重要的接口一定要做好限流策略,防止用戶惡意刷接口,同時(shí)要降級(jí)準(zhǔn)備,當(dāng)接口中的某些服務(wù)不可用時(shí)候,進(jìn)行熔斷,失敗快速返回機(jī)制。

1.3 緩存雪崩

1.3.1 問(wèn)題來(lái)源

緩存雪崩是指Redis緩存不能正常提供服務(wù)了(阻塞、服務(wù)宕機(jī)、大面積緩存失效等造成),導(dǎo)致所有請(qǐng)求都落到了數(shù)據(jù)庫(kù)上,增加了數(shù)據(jù)庫(kù)壓力或者導(dǎo)致數(shù)據(jù)庫(kù)宕機(jī)。

1.3.2 解決方案

1.3.2.1 緩存過(guò)期時(shí)間隨機(jī)

緩存數(shù)據(jù)的過(guò)期時(shí)間設(shè)置隨機(jī),防止同一時(shí)間大量數(shù)據(jù)過(guò)期現(xiàn)象發(fā)生。

1.3.2.2 分布式部署

采用分布式部署方式部署緩存,避免緩存服務(wù)單節(jié)點(diǎn),同時(shí)將熱點(diǎn)數(shù)據(jù)均勻分布在不同的緩存數(shù)據(jù)庫(kù)中。

1.3.2.3 設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過(guò)期

可以在刷緩存時(shí),設(shè)置熱點(diǎn)數(shù)據(jù)不過(guò)期。

1.3.2.4 接口限流與熔斷,降級(jí)

重要的接口一定要做好限流策略,防止用戶惡意刷接口,同時(shí)要降級(jí)準(zhǔn)備,當(dāng)接口中的某些服務(wù)不可用時(shí)候,進(jìn)行熔斷,失敗快速返回機(jī)制。

二、緩存更新機(jī)制

2.1 緩存更新策略分類

內(nèi)存淘汰超時(shí)剔除主動(dòng)更新
說(shuō)明重要的接口一定要做好限流策略,防止用戶惡意刷接口,同時(shí)要降級(jí)準(zhǔn)備,當(dāng)接口中的某些服務(wù)不可用時(shí)候,進(jìn)行熔斷,失敗快速返回機(jī)制。給緩存數(shù)據(jù)添加TTL時(shí)間,到期后自動(dòng)刪除緩存,下次查詢時(shí)更新緩存編寫(xiě)業(yè)務(wù)邏輯,在修改數(shù)據(jù)的同時(shí),更新緩存
一致性一般
維護(hù)成本無(wú)

2.2 內(nèi)存淘汰機(jī)制

2.2.1 noeviction

不淘汰,這是默認(rèn)的淘汰策略;

當(dāng)內(nèi)存達(dá)到限制后,寫(xiě)請(qǐng)求(set)會(huì)返回錯(cuò)誤,讀請(qǐng)求(get)和刪除請(qǐng)求(del)可以繼續(xù)進(jìn)行

2.2.2 volatile-lru

內(nèi)存不足時(shí),在設(shè)置了過(guò)期時(shí)間的key中,優(yōu)先刪除最近最少使用的key

2.2.3 volatile-lfu

內(nèi)存不足時(shí),在設(shè)置了過(guò)期時(shí)間的key中,優(yōu)先刪除使用頻率最少的key

2.2.4 volatile-ttl

內(nèi)存不足時(shí),在設(shè)置了過(guò)期時(shí)間的key中,優(yōu)先刪除存活剩余時(shí)間最少的key

2.2.5 volatile-random

內(nèi)存不足時(shí),在設(shè)置了過(guò)期時(shí)間的key中,隨機(jī)刪除某個(gè)key

2.2.6 allkey-lru

內(nèi)存不足時(shí),在全體key范圍內(nèi),優(yōu)先刪除最近最少使用的key

2.2.7 allkey-lfu

內(nèi)存不足時(shí),在全體key范圍內(nèi),優(yōu)先刪除使用頻率最少的key

2.2.8 allkey-random

內(nèi)存不足時(shí),在全體key范圍內(nèi),隨機(jī)刪除某個(gè)key

2.3 超時(shí)剔除

2.3.1 定時(shí)刪除

設(shè)置一個(gè)定時(shí)任務(wù),隨機(jī)抽取部分過(guò)期時(shí)間的key,檢查是否過(guò)期,過(guò)期了就清除掉

2.3.2 惰性刪除

查詢獲取數(shù)據(jù)時(shí),檢查緩存是否過(guò)期,過(guò)期則刪除,沒(méi)過(guò)期不刪除

Redis 默認(rèn)采用惰性刪除+定時(shí)刪除結(jié)合的過(guò)期策略

2.4 主動(dòng)更新

2.4.1 主動(dòng)更新策略

2.4.1.1 Cache Aside Pattern

  • 由緩存的調(diào)用者
  • 在更新數(shù)據(jù)庫(kù)的同時(shí)更新緩存

2.4.1.2 Read/Write Through Pattern

  • 緩存和數(shù)據(jù)庫(kù)整合為一個(gè)服務(wù),由服務(wù)來(lái)維護(hù)一致性。
  • 調(diào)用者調(diào)用服務(wù),不用關(guān)心一致性問(wèn)題。

2.4.1.3 Write Behind Caching Pattern

調(diào)用者只操作緩存,由其他線程異步的將緩存數(shù)據(jù)持久化到數(shù)據(jù)庫(kù),最終保持一致。

在企業(yè)中使用最多的主動(dòng)更新策略是 Cache Aside Pattern。也就是我們自己編碼來(lái)保證數(shù)據(jù)的一致性。

2.4.2 主動(dòng)更新策略需要考慮的三個(gè)問(wèn)題

2.4.1 刪除緩存還是更新緩存?

  • 2.4.1.1 刪除緩存

更新數(shù)據(jù)庫(kù)時(shí)讓緩存失效,查詢時(shí)再更新緩存。(延遲加載)一般選擇這個(gè)方案。

這個(gè)方案比較合理一點(diǎn),可以避免過(guò)多的無(wú)效寫(xiě)操作,緩存刪除后,只要沒(méi)人來(lái)查詢這條數(shù)據(jù),數(shù)據(jù)就不會(huì)被寫(xiě)入緩存,這樣就可以避免大量無(wú)效的寫(xiě)操作

  • 2.4.1.2 更新緩存

每次更新數(shù)據(jù)庫(kù)都更新緩存,無(wú)效寫(xiě)操作比較多。

這種方式的缺點(diǎn)很明顯,舉個(gè)例子:假如我更新了100次數(shù)據(jù)庫(kù),然后又同時(shí)更新了100次緩存,但是在更新的時(shí)候并沒(méi)有人來(lái)查這個(gè)數(shù)據(jù),那么我更新這100次緩存好像也沒(méi)啥用吧,相當(dāng)于前99次都是無(wú)用功,只有最后一次才是有用的。這就是無(wú)效寫(xiě)操作過(guò)多的原因。

2.4.2 如何保證緩存與數(shù)據(jù)庫(kù)的操作同時(shí)成功或失???

1)單體系統(tǒng),將緩存與數(shù)據(jù)庫(kù)操作放在一個(gè)事務(wù)中。

2)分布式系統(tǒng),利用TCC等分布式事務(wù)方案。

2.4.3 先操作緩存還是數(shù)據(jù)庫(kù)?

  • 2.4.3.1 先刪除緩存,再操作數(shù)據(jù)庫(kù)

這種方式存在很明顯的問(wèn)題,假設(shè)有兩個(gè)并發(fā)操作,線程A更新,線程B查詢。線程A先刪除緩存,然后還沒(méi)來(lái)得及更新數(shù)據(jù)庫(kù),CPU資源被線程B搶走,線程B查詢緩存發(fā)現(xiàn)沒(méi)有命中(因?yàn)橐呀?jīng)被線程A刪除了),查詢數(shù)據(jù)庫(kù),然后把結(jié)果寫(xiě)入到緩存中。這個(gè)時(shí)候線程A終于搶到CPU資源了,然后更新數(shù)據(jù)庫(kù),此時(shí)就會(huì)造成數(shù)據(jù)不一致問(wèn)題。

  • 2.4.3.2 先操作數(shù)據(jù)庫(kù),再刪除緩存

這種處理方式使用的頻率是最高的,因?yàn)槌鲥e(cuò)的概率非常小,只有一種比較極端的情況才會(huì)出現(xiàn)數(shù)據(jù)一致性問(wèn)題。

同樣有兩個(gè)并發(fā)請(qǐng)求,線程A查詢、線程B更新,當(dāng)線程A查詢的時(shí)候,緩存剛好失效,然后就去查詢數(shù)據(jù)庫(kù)拿到數(shù)據(jù),在準(zhǔn)備寫(xiě)入緩存的時(shí)候,CPU資源被線程B搶走,線程B開(kāi)始更新數(shù)據(jù)庫(kù),然后刪除緩存(這一步其實(shí)等于無(wú)用,因?yàn)榫彺嬉呀?jīng)過(guò)期)。此時(shí)線程A再次獲取到CPU資源,然后寫(xiě)入緩存,此時(shí)寫(xiě)入的是更新前的舊數(shù)據(jù),會(huì)產(chǎn)生數(shù)據(jù)一致性問(wèn)題。

看起來(lái)這確實(shí)也是一個(gè)問(wèn)題,但是我們仔細(xì)分析一下這種情況都需要滿足哪些條件:

  • 1)并發(fā)讀寫(xiě)操作
  • 2)讀緩存時(shí),緩存剛好失效
  • 3)寫(xiě)數(shù)據(jù)庫(kù)操作要比寫(xiě)緩存快

寫(xiě)數(shù)據(jù)庫(kù)是操作磁盤(pán),寫(xiě)緩存是操作內(nèi)存的,所以不太可能會(huì)出現(xiàn)寫(xiě)磁盤(pán)的速度快于寫(xiě)內(nèi)存的。因此使用這種方式出現(xiàn)數(shù)據(jù)一致性的概率是很小的。

  • 2.4.3.3 延時(shí)雙刪策略

延遲雙刪策略是分布式系統(tǒng)中數(shù)據(jù)庫(kù)存儲(chǔ)和緩存數(shù)據(jù)保持一致性的常用策略,但它不是強(qiáng)一致。其實(shí)不管哪種方案,都避免不了Redis存在臟數(shù)據(jù)的問(wèn)題,只能減輕這個(gè)問(wèn)題,要想徹底解決,得要用到同步鎖和對(duì)應(yīng)的業(yè)務(wù)邏輯層面解決。

前面兩種方案的不足點(diǎn)我們進(jìn)行了分析,第二種方式的使用頻率比較高,但是也有一些小缺陷,雖然說(shuō)發(fā)生的概率很低,但是這個(gè)概率到了線上會(huì)不會(huì)發(fā)生也不好說(shuō),所以就有了延時(shí)雙刪策略對(duì)第二種方式做補(bǔ)充。

所謂延時(shí)雙刪就是先進(jìn)行緩存清除,再執(zhí)行數(shù)據(jù)庫(kù)操作,最后(延遲N秒)再執(zhí)行緩存清除。延遲N秒的時(shí)間要大于一次寫(xiě)操作的時(shí)間,這個(gè)延時(shí)N秒就是了完善保證第二種策略中不足,可以保證線程A的寫(xiě)緩存和線程B的修改數(shù)據(jù)庫(kù)、刪除緩存都執(zhí)行完畢,然后再刪除緩存一次,就可以保證后面再來(lái)的查詢請(qǐng)求可以查詢到最新數(shù)據(jù)。

ps: 一般的延時(shí)時(shí)間設(shè)置為3S左右,具體情況要根據(jù)業(yè)務(wù)場(chǎng)景取最佳值。

2.5 緩存更新機(jī)制總結(jié)

  • 1)內(nèi)存淘汰:不用自己維護(hù),利用Redis內(nèi)存淘汰機(jī)制,自動(dòng)刪除部分緩存數(shù)據(jù),這些被刪除的數(shù)據(jù)在下一次被查詢時(shí)更新。這種方式一致性最差。
  • 2)超時(shí)剔除:給緩存數(shù)據(jù)加上過(guò)期時(shí)間 ,到期后自動(dòng)刪除,下次查詢時(shí)更新,數(shù)據(jù)一致性問(wèn)題大概率會(huì)出現(xiàn)。維護(hù)成本比較低。
  • 3)主動(dòng)更新:編寫(xiě)業(yè)務(wù)邏輯,在修改數(shù)據(jù)庫(kù)的同時(shí)更新緩存,一致性比較好,維護(hù)成本比較高。一般采用先操作數(shù)據(jù)庫(kù)再更新緩存的方式。

一般在數(shù)據(jù)一致性要求比較低的場(chǎng)景下可以使用內(nèi)存淘汰機(jī)制,比如商城首頁(yè)的分類信息,這些東西基本上是不會(huì)變化的。如果一致性要求比較高,我們可以采用主動(dòng)更新+超時(shí)剔除兜底的方式來(lái)處理。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • redis基本安裝判斷、啟動(dòng)使用方法示例

    redis基本安裝判斷、啟動(dòng)使用方法示例

    這篇文章主要介紹了redis基本安裝判斷、啟動(dòng)使用方法,結(jié)合實(shí)例形式分析了Redis針對(duì)是否安裝的判斷、啟動(dòng)等使用方法,需要的朋友可以參考下
    2020-02-02
  • Redis內(nèi)存空間占用及避免數(shù)據(jù)丟失的方法

    Redis內(nèi)存空間占用及避免數(shù)據(jù)丟失的方法

    在現(xiàn)代的互聯(lián)網(wǎng)應(yīng)用中,Redis作為一種高性能的內(nèi)存數(shù)據(jù)庫(kù),被廣泛應(yīng)用于緩存、會(huì)話管理和消息隊(duì)列等場(chǎng)景,然而,Redis的內(nèi)存資源是有限的,過(guò)多的內(nèi)存占用可能會(huì)導(dǎo)致數(shù)據(jù)丟失所以本文將給大家介紹一下Redis內(nèi)存空間占用及避免數(shù)據(jù)丟失的方法
    2023-08-08
  • Redis連接錯(cuò)誤的情況總結(jié)分析

    Redis連接錯(cuò)誤的情況總結(jié)分析

    這篇文章主要給大家總結(jié)介紹了關(guān)于Redis連接錯(cuò)誤的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • Windows下redis下載、redis安裝及使用教程

    Windows下redis下載、redis安裝及使用教程

    redis 提供了多種數(shù)據(jù)類型來(lái)支持不同的業(yè)務(wù)場(chǎng)景,所以經(jīng)常使用在分布式鎖中,今天給大家講解redis安裝及使用教程,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • 淺談Redis緩存雪崩解決方案

    淺談Redis緩存雪崩解決方案

    本文主要介紹了Redis緩存雪崩解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 淺析Redis中String數(shù)據(jù)類型及其底層編碼

    淺析Redis中String數(shù)據(jù)類型及其底層編碼

    這篇文章主要介紹?Redis?中?String?數(shù)據(jù)類型及其底層編碼,文中有詳細(xì)的代碼示例,對(duì)大家的工作及學(xué)習(xí)有一定的幫助,需要的朋友可以參考下
    2023-05-05
  • Redis并發(fā)問(wèn)題解決方案

    Redis并發(fā)問(wèn)題解決方案

    在當(dāng)前的互聯(lián)網(wǎng)環(huán)境中,高并發(fā)業(yè)務(wù)場(chǎng)景十分常見(jiàn),本文就來(lái)介紹一下Redis并發(fā)問(wèn)題解決方案,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • 一起raid數(shù)據(jù)恢復(fù)及回遷成功的案例

    一起raid數(shù)據(jù)恢復(fù)及回遷成功的案例

    這篇文章主要介紹了一起raid數(shù)據(jù)恢復(fù)及回遷成功的案例,需要的朋友可以參考下
    2017-04-04
  • Redis遍歷所有key的兩個(gè)命令(KEYS 和 SCAN)

    Redis遍歷所有key的兩個(gè)命令(KEYS 和 SCAN)

    這篇文章主要介紹了Redis遍歷所有key的兩個(gè)命令(KEYS 和 SCAN),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • redis部署及各種數(shù)據(jù)類型使用命令詳解

    redis部署及各種數(shù)據(jù)類型使用命令詳解

    這篇文章主要介紹了redis部署及各種數(shù)據(jù)類型使用命令,編譯安裝redis及部署過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03

最新評(píng)論