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

Redis緩存問題與緩存更新機制詳解

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

一、緩存問題

1.1 緩存穿透

1.1.1 問題來源

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

1.1.2 解決方案

1.1.2.1 緩存空對象

  • 從緩存取不到的數(shù)據(jù),在數(shù)據(jù)庫中也沒有取到,這時也可以將key-value對寫為key-null,緩存有效時間可以設置短點,如30秒(設置太長會導致正常情況也沒法使用)。
  • 這樣可以防止攻擊用戶反復用同一個id暴力攻擊。

1.1.2.2 使用布隆過濾器

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

1.2 緩存擊穿

1.2.1 問題來源

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

1.2.2 解決方案

1.2.2.1 設置熱點數(shù)據(jù)永遠不過期

可以在刷緩存時,設置熱點數(shù)據(jù)不過期。

1.2.2.2 新增后臺定時更新緩存線程(邏輯不過期)

后臺新增一個緩存更新線程,緩存快要過期前刷新緩存時間,防止緩存失效。

1.2.2.3 使用分布式互斥鎖

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

1.2.2.4 接口限流與熔斷,降級

重要的接口一定要做好限流策略,防止用戶惡意刷接口,同時要降級準備,當接口中的某些服務不可用時候,進行熔斷,失敗快速返回機制。

1.3 緩存雪崩

1.3.1 問題來源

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

1.3.2 解決方案

1.3.2.1 緩存過期時間隨機

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

1.3.2.2 分布式部署

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

1.3.2.3 設置熱點數(shù)據(jù)永遠不過期

可以在刷緩存時,設置熱點數(shù)據(jù)不過期。

1.3.2.4 接口限流與熔斷,降級

重要的接口一定要做好限流策略,防止用戶惡意刷接口,同時要降級準備,當接口中的某些服務不可用時候,進行熔斷,失敗快速返回機制。

二、緩存更新機制

2.1 緩存更新策略分類

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

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

2.2.1 noeviction

不淘汰,這是默認的淘汰策略;

當內(nèi)存達到限制后,寫請求(set)會返回錯誤,讀請求(get)和刪除請求(del)可以繼續(xù)進行

2.2.2 volatile-lru

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

2.2.3 volatile-lfu

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

2.2.4 volatile-ttl

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

2.2.5 volatile-random

內(nèi)存不足時,在設置了過期時間的key中,隨機刪除某個key

2.2.6 allkey-lru

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

2.2.7 allkey-lfu

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

2.2.8 allkey-random

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

2.3 超時剔除

2.3.1 定時刪除

設置一個定時任務,隨機抽取部分過期時間的key,檢查是否過期,過期了就清除掉

2.3.2 惰性刪除

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

Redis 默認采用惰性刪除+定時刪除結(jié)合的過期策略

2.4 主動更新

2.4.1 主動更新策略

2.4.1.1 Cache Aside Pattern

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

2.4.1.2 Read/Write Through Pattern

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

2.4.1.3 Write Behind Caching Pattern

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

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

2.4.2 主動更新策略需要考慮的三個問題

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

  • 2.4.1.1 刪除緩存

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

這個方案比較合理一點,可以避免過多的無效寫操作,緩存刪除后,只要沒人來查詢這條數(shù)據(jù),數(shù)據(jù)就不會被寫入緩存,這樣就可以避免大量無效的寫操作

  • 2.4.1.2 更新緩存

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

這種方式的缺點很明顯,舉個例子:假如我更新了100次數(shù)據(jù)庫,然后又同時更新了100次緩存,但是在更新的時候并沒有人來查這個數(shù)據(jù),那么我更新這100次緩存好像也沒啥用吧,相當于前99次都是無用功,只有最后一次才是有用的。這就是無效寫操作過多的原因。

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

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

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

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

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

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

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

這種處理方式使用的頻率是最高的,因為出錯的概率非常小,只有一種比較極端的情況才會出現(xiàn)數(shù)據(jù)一致性問題。

同樣有兩個并發(fā)請求,線程A查詢、線程B更新,當線程A查詢的時候,緩存剛好失效,然后就去查詢數(shù)據(jù)庫拿到數(shù)據(jù),在準備寫入緩存的時候,CPU資源被線程B搶走,線程B開始更新數(shù)據(jù)庫,然后刪除緩存(這一步其實等于無用,因為緩存已經(jīng)過期)。此時線程A再次獲取到CPU資源,然后寫入緩存,此時寫入的是更新前的舊數(shù)據(jù),會產(chǎn)生數(shù)據(jù)一致性問題。

看起來這確實也是一個問題,但是我們仔細分析一下這種情況都需要滿足哪些條件:

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

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

  • 2.4.3.3 延時雙刪策略

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

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

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

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

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

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

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

總結(jié)

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

相關(guān)文章

  • redis基本安裝判斷、啟動使用方法示例

    redis基本安裝判斷、啟動使用方法示例

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

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

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

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

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

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

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

    淺談Redis緩存雪崩解決方案

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

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

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

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

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

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

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

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

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

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

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

最新評論