Redis 之七:穿透、擊穿、雪崩

(本內容部分來自知乎網等網絡)

Redis 緩存的使用,極大的提升了應用程序的性能和效率,特別是數據查詢方面。但同時,它也帶來了一些問題。其中,最要害的問題,就是數據的一致性問題,從嚴格意義上講,這個問題無解。如果對數據 的一致性要求很高,那么就不能使用緩存。

另外的一些典型問題就是,緩存穿透、緩存雪崩和緩存擊穿。目前,業界也都有比較流行的解決方案。

1. 緩存穿透(數據不存在)

緩存穿透是指查詢請求中的數據在緩存系統和后端數據庫中都不存在的情況。

正常情況下,如果數據不在緩存中,會去數據庫查詢并把結果放入緩存以備后續使用。但如果惡意或者大量請求都是針對不存在的數據,那么這些請求將會繞過緩存直接打到數據庫,導致數據庫承受不必要的壓力。

解決方案
  • 布隆過濾器(Bloom Filter):可以在查詢緩存之前先通過布隆過濾器判斷該 key 是否可能存在,如果布隆過濾器認為不存在,則直接返回空,避免對數據庫進行查詢。
  • 空值緩存:即使從數據庫查不到數據,也把一個特殊值(比如NULLFLAG)作為結果緩存起來,設置較短的過期時間,這樣短期內連續針對同樣不存在的數據的請求也能被緩存攔截。
布隆過濾器

布隆過濾器: 是一種數據結構,對所有可能查詢的參數以hash形式存儲,在控制層先進行校驗,不符合則 丟棄,從而避免了對底層存儲系統的查詢壓力;

什么是布隆過濾器

本質上布隆過濾器是一種數據結構,比較巧妙的概率型數據結構(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你?“某樣東西一定不存在或者可能存在”

相比于傳統的 List、Set、Map 等數據結構,它更高效、占用空間更少,但是缺點是其返回的結果是概率性的,而不是確切的。

什么是布隆過濾器

本質上布隆過濾器是一種數據結構,比較巧妙的概率型數據結構(probabilistic data structure),特點是高效地插入和查詢,可以用來告訴你?“某樣東西一定不存在或者可能存在”

相比于傳統的 List、Set、Map 等數據結構,它更高效、占用空間更少,但是缺點是其返回的結果是概率性的,而不是確切的。

實現原理

HashMap 的問題

講述布隆過濾器的原理之前,我們先思考一下,通常你判斷某個元素是否存在用的是什么?應該蠻多人回答 HashMap 吧,確實可以將值映射到 HashMap 的 Key,然后可以在 O(1) 的時間復雜度內返回結果,效率奇高。但是 HashMap 的實現也有缺點,例如存儲容量占比高,考慮到負載因子的存在,通常空間是不能被用滿的,而一旦你的值很多例如上億的時候,那 HashMap 占據的內存大小就變得很可觀了。

還比如說你的數據集存儲在遠程服務器上,本地服務接受輸入,而數據集非常大不可能一次性讀進內存構建 HashMap 的時候,也會存在問題。

布隆過濾器數據結構

布隆過濾器是一個 bit 向量或者說 bit 數組,長這樣:

如果我們要映射一個值到布隆過濾器中,我們需要使用多個不同的哈希函數生成多個哈希值,并對每個生成的哈希值指向的 bit 位置 1,例如針對值 “baidu” 和三個不同的哈希函數分別生成了哈希值 1、4、7,則上圖轉變為:

Ok,我們現在再存一個值 “tencent”,如果哈希函數返回 3、4、8 的話,圖繼續變為:

值得注意的是,4 這個 bit 位由于兩個值的哈希函數都返回了這個 bit 位,因此它被覆蓋了。現在我們如果想查詢 “dianping” 這個值是否存在,哈希函數返回了 1、5、8三個值,結果我們發現 5 這個 bit 位上的值為 0,說明沒有任何一個值映射到這個 bit 位上,因此我們可以很確定地說 “dianping” 這個值不存在。而當我們需要查詢 “baidu” 這個值是否存在的話,那么哈希函數必然會返回 1、4、7,然后我們檢查發現這三個 bit 位上的值均為 1,那么我們可以說 “baidu”?存在了么?答案是不可以,只能是 “baidu” 這個值可能存在。

這是為什么呢?答案跟簡單,因為隨著增加的值越來越多,被置為 1 的 bit 位也會越來越多,這樣某個值 “taobao” 即使沒有被存儲過,但是萬一哈希函數返回的三個 bit 位都被其他值置位了 1 ,那么程序還是會判斷 “taobao” 這個值存在。

如何選擇哈希函數個數和布隆過濾器長度

很顯然,過小的布隆過濾器很快所有的 bit 位均為 1,那么查詢任何值都會返回“可能存在”,起不到過濾的目的了。布隆過濾器的長度會直接影響誤報率,布隆過濾器越長其誤報率越小。

另外,哈希函數的個數也需要權衡,個數越多則布隆過濾器 bit 位置位 1 的速度越快,且布隆過濾器的效率越低;但是如果太少的話,那我們的誤報率會變高。


k 為哈希函數個數,m 為布隆過濾器長度,n 為插入的元素個數,p 為誤報率

緩存空對象

當存儲層不命中后,即使返回的空對象也將其緩存起來,同時會設置一個過期時間,之后再訪問這個數 據將會從緩存中獲取,保護了后端數據源;

但是這種方法會存在兩個問題:

1、如果空值能夠被緩存起來,這就意味著緩存需要更多的空間存儲更多的鍵,因為這當中可能會有很多的空值的鍵;

2、即使對空值設置了過期時間,還是會存在緩存層和存儲層的數據會有一段時間窗口的不一致,這對于需要保持一致性的業務會有影響。

2. 緩存擊穿(緩存過期)

定義: 緩存擊穿通常指的是某個熱點數據過期失效后,短時間內有大量的并發請求同時來訪問這個剛剛過期的數據,從而所有請求都會穿透緩存直接到達數據庫,造成數據庫瞬間壓力過大。

解決方法

  • 互斥鎖(Mutex Lock):對于熱點數據,在緩存失效時采用加鎖策略,使得只有一個線程能持有鎖去數據庫加載數據,其他線程等待鎖釋放后獲取更新后的緩存數據。
  • 永不過期:在業務允許的情況下,可以考慮讓熱點數據永不超時,而是通過定時任務或后臺異步刷新的方式更新緩存。

這里需要注意和緩存擊穿的區別,緩存擊穿,是指一個key非常熱點,在不停的扛著大并發,大并發集中 對這一個點進行訪問,當這個key在失效的瞬間,持續的大并發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。

當某個key在過期的瞬間,有大量的請求并發訪問,這類數據一般是熱點數據,由于緩存過期,會同時訪問數據庫來查詢最新數據,并且回寫緩存,會導使數據庫瞬間壓力過大。

設置熱點數據永不過期

從緩存層面來看,沒有設置過期時間,所以不會出現熱點 key 過期后產生的問題。

加互斥鎖

分布式鎖:使用分布式鎖,保證對于每個key同時只有一個線程去查詢后端服務,其他線程沒有獲得分布式鎖的權限,因此只需要等待即可。這種方式將高并發的壓力轉移到了分布式鎖,因此對分布式鎖的考驗很大。

3. 緩存雪崩

定義: 緩存雪崩是指緩存集群在某一時刻大面積地發生緩存失效,例如由于網絡抖動、緩存服務器宕機、或者大量緩存同時達到預設過期時間等導致。此時,原本由緩存承載的大量請求全部涌入數據庫,可能會壓垮數據庫。

緩存雪崩,是指在某一個時間段,緩存集中過期失效。Redis 宕機!

產生雪崩的原因之一,比如在寫本文的時候,馬上就要到雙十二零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了緩存,假設緩存一個小時。那么到了凌晨一點鐘的時候,這批商品的緩存就都過期了。而對這批商品的訪問查詢,都落到了數據庫上,對于數據庫而言,就會產生周期性的壓力波峰。于是所有的請求都會達到存儲層,存儲層的調用量會暴增,造成存儲層也會掛掉的情況。

解決方法

  • 分散失效時間:為緩存設置隨機的過期時間,防止大量緩存在同一時刻失效。
  • 多級緩存:使用主從、集群等方式部署緩存,增強緩存系統的可用性。
  • 熔斷降級與限流:當數據庫壓力過大時,可以通過熔斷機制暫時停止向數據庫發送請求,并啟動降級策略;同時也可以使用限流措施控制請求流量,保護數據庫不受沖擊。
  • 提前預熱:在緩存失效前提前刷新緩存,尤其對于那些即將過期的熱點數據。

其實集中過期,倒不是非常致命,比較致命的緩存雪崩,是緩存服務器某個節點宕機或斷網。因為自然形成的緩存雪崩,一定是在某個時間段集中創建緩存,這個時候,數據庫也是可以頂住壓力的。無非就是對數據庫產生周期性的壓力而已。而緩存服務節點的宕機,對數據庫服務器造成的壓力是不可預知的,很有可能瞬間就把數據庫壓垮。

綜上所述,要應對這三種情況,需要結合具體的業務場景,合理設計緩存策略,以及利用額外的技術手段來保證系統的穩定性和高可用性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714380.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714380.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714380.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Educational Codeforces Round 132 (Rated for Div. 2) E. XOR Tree(啟發式合并+貪心)

題目 n(n<2e5)個點的樹&#xff0c;點i權值ai&#xff08;1<ai<2^30&#xff09; 修改最少的點的權值&#xff0c;使得樹上不存在異或和為0的簡單路徑&#xff0c;輸出最少的點數 權值可以被修改成任意正整數&#xff08;可以是無限大&#xff09; 思路來源 官方…

【leetcode】環形鏈表?環形鏈表II

大家好&#xff0c;我是蘇貝&#xff0c;本篇博客帶大家刷題&#xff0c;如果你覺得我寫的還不錯的話&#xff0c;可以給我一個贊&#x1f44d;嗎&#xff0c;感謝?? 目錄 1.環形鏈表解題拓展&#xff1a; 2.環形鏈表II 1.環形鏈表 點擊查看題目 解題 思路: bool hasCycle…

【算法集訓】基礎算法:基礎排序 - 插入排序

一、基本理解 插入排序(nsertion Sort)&#xff0c;一般也被稱為直接插入排序&#xff0c;是一種簡單直觀的排序算法。 **工作原理&#xff1a;**將待排列元素劃分為「已排序」和「未排序」兩部分&#xff0c;每次從「未排序的」元素中選 擇一個插入到「已排序的」元素中的正確…

劍指offer58—II 左旋轉字符串 c++

題目 字符串的左旋轉操作是把字符串前面的若干個字符轉移到字符串的尾部。請定義一個函數實現字符串左旋轉操作的功能。比如,輸入字符串"abcdefg"和數字2,該函數將返回左旋轉兩位得到的結果"cdefgab"。 示例 1: 輸入: s = “abcdefg”, k = 2 輸出: “…

MySQL 多表查詢 連接查詢 內連接

介紹 內連接查詢是兩張表中交集的部分 連接模式 隱式內連接 SELECT 字段列表 FROM 表1,表2 WHERE 條件顯式內連接 SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 連接條件案例 有兩張表一個表為學生表&#xff0c;另一個表為班級表&#xff0c;現在需要查詢學生時候在查…

接口測試(全)

&#x1f345; 視頻學習&#xff1a;文末有免費的配套視頻可觀看 &#x1f345; 關注公眾號【互聯網雜貨鋪】&#xff0c;回復 1 &#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 大多數人對于接口測試都覺得是一種高大上的測試&#xff0c;覺得…

羊大師分析,羊奶粉適合什么樣的人群喝

羊大師分析&#xff0c;羊奶粉適合什么樣的人群喝 羊奶粉適合多種人群食用&#xff0c;包括兒童、老年人、孕婦以及身體虛弱或處于疾病康復期的人群。 對于兒童來說&#xff0c;羊奶粉是一種很好的營養品。它含有豐富的蛋白質、脂肪、礦物質和維生素&#xff0c;能夠滿足兒童…

【前端素材】推薦優質后臺管理系統網頁Star admin平臺模板(附源碼)

一、需求分析 1、系統定義 后臺管理系統是一種用于管理和控制網站、應用程序或系統的管理界面。它通常被設計用來讓網站或應用程序的管理員或運營人員管理內容、用戶、數據以及其他相關功能。后臺管理系統是一種用于管理網站、應用程序或系統的工具&#xff0c;通常由管理員使…

三種圖片預覽插件viewer、vue-photo-preview、vue-picture-preview

第一種&#xff1a;viewerjs使用介紹 1、先安裝依賴 npm install v-viewer --save2、main.js內引用并注冊調用 //main.js import Viewer from ‘v-viewer’ import ‘viewerjs/dist/viewer.css’ Vue.use(Viewer); Viewer.setDefaults({ Options: { “inline”: true, “butt…

王志亮出席海爾智慧樓宇發酵行業的低碳節能解決方案

演講嘉賓&#xff1a;王志亮 食品醫藥用戶群總監 青島海爾空調電子有限公司 演講題目&#xff1a;海爾智慧樓宇在發酵行業的低碳、節能解決方案 會議簡介 “十四五”規劃中提出&#xff0c;提高工業、能源領城智能化與信息化融合&#xff0c;明確“低碳經濟”新的戰略目標&…

System Verilog學習筆記(十一)——數組(1)

System Verilog學習筆記&#xff08;十一&#xff09;——數組&#xff08;1&#xff09; 非組合型&#xff08;unpacked&#xff09; 成員之間存儲數據都是相互獨立的可以索引非組合型數組或者數組片段的能力聲明方式&#xff1a; logic [31&#xff1a;0] data [1024]; lo…

黑馬JUC筆記

黑馬JUC筆記 1.概覽 2.進程與線程 2.1 進程與線程 進程 程序由指令和數據組成&#xff0c;但這些指令要運行&#xff0c;數據要讀寫&#xff0c;就必須將指令加載至 CPU&#xff0c;數據加載至內存。在 指令運行過程中還需要用到磁盤、網絡等設備。進程就是用來加載指令、管…

Cisco Secure ACS 5.8.0.32 安裝 + Crack 教程

Cisco Secure ACS 5.8.0.32 安裝 Crack 教程 前言系統環境開始安裝 開始破解導入授權文件 前言 在ESXi 6.7 上經歷過無數次的安裝嘗試 測試了各種兼容版本都沒有安裝成功,記最后一次安裝成功的過程. 系統環境 服務器 : Dell R720xd CPU : E5-2620 v2 系統 : ESXi 6.7…

簡單控件屬性設置

1、設置文本的內容 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"…

十四、Qt主機信息與網絡編程

一、主機信息 1、主機信息接口 QHostInfo&#xff1a;獲取主機名稱和IP地址QNetWorkInterface&#xff1a;獲取主機的所有網絡接口&#xff0c;包括子網掩碼和廣播地址等 &#xff08;1&#xff09;使用 項目添加模塊QT network2、實現程序 &#xff08;1&#xff0…

【01】openEuler 源碼安裝 PostgreSQL

openEuler 源碼安裝 PostgreSQL 部署環境說明Shell 前端軟件包管理器基礎概念YUM 簡介DNF 簡介 源碼安裝 PostgreSQL環境變量&#xff08;env&#xff09;設置臨時環境變量設置永久環境變量設置 初始化數據庫&#xff08;initdb&#xff09; 數據庫基本操作數據庫基本配置&…

WiFi協議的調制技術介紹

調制技術是WiFi協議的核心部分&#xff0c;它負責將數據轉換成可以在無線信道中傳輸的信號。WiFi協議采用正交頻分復用&#xff08;OFDM&#xff09;調制技術&#xff0c;該技術通過將數據分成多個子載波進行傳輸&#xff0c;提高了信道利用率和抗干擾能力。 OFDM調制的工作原…

推特API(Twitter API)V2 用戶關注

前面章節已經介紹使用code換取Token的整個流程了&#xff0c;這里不再重復闡述了&#xff0c;下面我們獲取到用戶token以后如何幫用戶自動關注別人。需要參數關注者的用戶ID&#xff08;token授權用戶&#xff09;以及關注的目標用戶ID。用戶ID如何獲取可以看上一章節獲取用戶信…

c++結構體內存對齊

結構體內存對齊 試試運行下面的例子 #include <stdio.h> #include <stdlib.h>using namespace std;struct A{char c;int i; };struct B{char c; int i; double d; };struct C{char c;int i;double d;char c1; };int main(){printf("sizeof(A): %d\n"…

SparkStreaming在實時處理的兩個場景示例

簡介 Spark Streaming是Apache Spark生態系統中的一個組件&#xff0c;用于實時流式數據處理。它提供了類似于Spark的API&#xff0c;使開發者可以使用相似的編程模型來處理實時數據流。 Spark Streaming的工作原理是將連續的數據流劃分成小的批次&#xff0c;并將每個批次作…