Redis---緩存穿透,雪崩,擊穿

文章目錄

    • 緩存穿透
      • 什么是緩存穿透?
      • 緩存穿透情況的處理流程是怎樣的?
      • 緩存穿透的解決辦法
        • 緩存無效 key
        • 布隆過濾器
    • 緩存雪崩
      • 什么是緩存雪崩?
      • 緩存雪崩的解決辦法
    • 緩存擊穿
      • 什么是緩存擊穿?
      • 緩存擊穿的解決辦法
    • 區別對比


在如今的開發中,使用緩存中間件 Redis 已經成為一項很廣泛的技術,Redis 的高性能大大優化了我們的服務器性能,緩解了在高并發的情況下服務器的壓力。它基于緩存的形式,在內存中保存數據,減少對磁盤的 IO 操作。然而盡管 Redis 有著很多的優點,但仍然有三朵烏云漂浮在 Redis 的上空:穿透,擊穿,雪崩

緩存穿透

什么是緩存穿透?

請求的數據既不在緩存中,也不在數據庫中(如惡意攻擊、非法ID查詢)。

緩存穿透說簡單點就是大量請求的 key 根本不存在于緩存中,導致請求直接到了數據庫上,根本沒有經過緩存這一層。舉個例子:某個黑客故意制造我們緩存中不存在的 key 發起大量請求,導致大量請求落到數據庫。

緩存穿透情況的處理流程是怎樣的?

用戶的請求最終都要跑到數據庫查詢一遍。

緩存穿透情況

緩存穿透的解決辦法

最基本的就是首先做好參數校驗,一些不合法的參數請求直接拋出異常信息返回給客戶端。比如查詢的數據庫 id 不能小于 0、傳入的郵箱格式不對的時候直接返回錯誤消息給客戶端等等。

緩存無效 key

如果緩存和數據庫都查不到某個 key 的數據就寫一個到 Redis 中去并 設置過期時間,具體命令如下: SET key value EX 10086 。這種方式 可以解決請求的 key 變化不頻繁的情況,如果黑客惡意攻擊,每次構建不同的請求 key,會導致 Redis 中緩存大量無效的 key 。很明顯,這種方案并不能從根本上解決此問題。如果非要用這種方式來解決穿透問題的話,盡量將無效的 key 的過期時間設置短一點比如 1 分鐘。

另外,這里多說一嘴,一般情況下我們是這樣設計 key 的: 表名:列名:主鍵名:主鍵值

如果用 Java 代碼展示的話,差不多是下面這樣的:

public Object getObjectInclNullById(Integer id) {// 從緩存中獲取數據Object cacheValue = cache.get(id);// 緩存為空if (cacheValue == null) {// 從數據庫中獲取Object storageValue = storage.get(key);// 緩存空對象cache.set(key, storageValue);// 如果存儲數據為空,需要設置一個過期時間(300秒)if (storageValue == null) {// 必須設置過期時間,否則有被攻擊的風險cache.expire(key, 60 * 5);}return storageValue;}return cacheValue;
}
布隆過濾器

更具體的布隆過濾器原理以及實現可以查看Redis—布隆過濾器-CSDN博客

布隆過濾器是一個非常神奇的數據結構,通過它我們可以非常方便地判斷一個給定數據是否存在于海量數據中。我們需要的就是判斷 key 是否合法,有沒有感覺布隆過濾器就是我們想要找的那個“人”。

具體是這樣做的:把所有可能存在的請求的值都存放在布隆過濾器中,當用戶請求過來,先判斷用戶發來的請求的值是否存在于布隆過濾器中。不存在的話,直接返回請求參數錯誤信息給客戶端,存在的話才會走下面的流程。

加入布隆過濾器之后的緩存處理流程圖如下。

image

但是,需要注意的是布隆過濾器可能會存在誤判的情況。總結來說就是: 布隆過濾器說某個元素存在,小概率會誤判。布隆過濾器說某個元素不在,那么這個元素一定不在。

為什么會出現誤判的情況呢? 我們還要從布隆過濾器的原理來說!

我們先來看一下,當一個元素加入布隆過濾器中的時候,會進行哪些操作:

  1. 使用布隆過濾器中的哈希函數對元素值進行計算,得到哈希值(有幾個哈希函數得到幾個哈希值)。
  2. 根據得到的哈希值,在位數組中把對應下標的值置為 1。

我們再來看一下,當我們需要判斷一個元素是否存在于布隆過濾器的時候,會進行哪些操作:

  1. 對給定元素再次進行相同的哈希計算;
  2. 得到值之后判斷位數組中的每個元素是否都為 1,如果值都為 1,那么說明這個值在布隆過濾器中,如果存在一個值不為 1,說明該元素不在布隆過濾器中。

然后,一定會出現這樣一種情況:不同的字符串可能哈希出來的位置相同。 (可以適當增加位數組大小或者調整我們的哈希函數來降低概率)

緩存雪崩

什么是緩存雪崩?

緩存雪崩描述的就是這樣一個簡單的場景:緩存在同一時間大面積的失效,后面的請求都直接落到了數據庫上,造成數據庫短時間內承受大量請求。 這就好比雪崩一樣,摧枯拉朽之勢,數據庫的壓力可想而知,可能直接就被這么多請求弄宕機了。

舉個例子:系統的緩存模塊出了問題比如宕機導致不可用。造成系統的所有訪問,都要走數據庫。

還有一種緩存雪崩的場景是:有一些被大量訪問數據(熱點緩存)在某一時刻大面積失效,導致對應的請求直接落到了數據庫上。 這樣的情況,有下面幾種解決辦法:

舉個例子 :秒殺開始 12 個小時之前,我們統一存放了一批商品到 Redis 中,設置的緩存過期時間也是 12 個小時,那么秒殺開始的時候,這些秒殺的商品的訪問直接就失效了。導致的情況就是,相應的請求直接就落到了數據庫上,就像雪崩一樣可怕。

緩存雪崩的解決辦法

針對 Redis 服務不可用的情況:

  1. 采用 Redis 集群,避免單機出現問題整個緩存服務都沒辦法使用。
  2. 限流,避免同時處理大量的請求。

針對熱點緩存失效的情況:

  1. 設置不同的失效時間比如隨機設置緩存的失效時間。
  2. 緩存永不失效。

緩存擊穿

什么是緩存擊穿?

緩存擊穿是指 ?某個熱點數據在緩存過期(失效)的瞬間?,大量并發請求直接穿透緩存,全部打到數據庫上,導致數據庫負載驟增甚至崩潰的現象。

緩存擊穿的解決辦法

  1. 互斥鎖:

原理?:當緩存失效時,只允許一個線程去查詢數據庫并重建緩存,其他線程等待鎖釋放后直接讀取新緩存。
?實現方式?:

  • ?分布式鎖?(如 Redis 的 SETNX 或 Redisson 的 RLock)。
  • ?本地鎖?(單機環境下可用 synchronizedReentrantLock)。
  1. 永不過期:

原理?:緩存不設置過期時間,通過 ?異步線程定期更新緩存?(如定時任務或消息隊列觸發)。
?實現方式?:

  • 緩存設置為永久有效。
  • 通過后臺任務或事件驅動更新數據。
  1. 緩存預熱

?原理?:在系統啟動或低峰期,提前加載熱點數據到緩存,避免首次請求穿透。
?實現方式?:

  • 統計歷史熱點數據(如 Top-N 訪問 Key)。
  • 通過腳本或定時任務預加載緩存。

?適用場景?:

  • 電商大促前預加載秒殺商品數據。
  • 新聞類應用預加載頭條內容。

區別對比

維度緩存穿透緩存雪崩緩存擊穿
?觸發條件?請求的數據==?既不在緩存,也不在數據庫?==(如無效ID、惡意攻擊)?大量緩存同時失效?(如集體過期或緩存服務宕機)?單個熱點數據過期失效?(如秒殺商品緩存到期)
?影響范圍?單個或多個無效數據請求?全局性?(大量緩存失效,導致數據庫壓力驟增)?局部性?(僅某個熱點數據失效,但并發極高)
?請求特征?大量==?無效請求?==(惡意或業務缺陷)大量==?有效請求?==因緩存失效直接訪問數據庫大量==?有效請求?==集中訪問同一失效熱點數據
?解決方案?1. 布隆過濾器
2. 緩存空值
3. 接口鑒權
1. 隨機過期時間
2. 多級緩存
3. 熔斷降級
1. 互斥鎖
2. 邏輯過期
3. 永不過期策略
?典型場景?爬蟲惡意掃描不存在的ID緩存服務宕機或批量設置相同TTL微博熱搜、秒殺活動等高并發場景

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

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

相關文章

Android Logcat 高效調試指南

工具概覽 Logcat 是 Android SDK 提供的命令行日志工具&#xff0c;支持靈活過濾、格式定制和實時監控&#xff0c;官方文檔詳見 Android Developer。 基礎用法 命令格式 [adb] logcat [<option>] ... [<filter-spec>] ... 執行方式 直接調用&#xff08;通過ADB守…

【定昌Linux系統】部署了java程序,設置開啟啟動

將代碼上傳到相應的目錄&#xff0c;并且配置了一個.sh的啟動腳本文件 文件內容&#xff1a; #!/bin/bash# 指定JAR文件的路徑&#xff08;如果JAR文件在當前目錄&#xff0c;可以直接使用文件名&#xff09; JAR_FILE"/usr/local/java/xs_luruan_client/lib/xs_luruan_…

Java 8 中,可以使用 Stream API 和 Comparator 對 List 按照元素對象的時間字段進行倒序排序

文章目錄 引言I 示例對象II List 按時間字段倒序排序: 使用 `Stream` 和 `Comparator` 排序方法 1:使用 `Comparator.comparing`方法 2:使用 `Comparator.reversed`方法 3:自定義 `Comparator`輸出結果III 注意事項**時間字段類型**:**空值處理**:IV 總結引言 案例:在線用…

jvm內存模型,類加載機制,GC算法,垃圾回收器,jvm線上調優等常見的面試題及答案

JVM內存模型 JVM內存模型包括哪些區域 答案&#xff1a;JVM內存模型主要包括以下區域&#xff1a; 程序計數器&#xff1a;是一塊較小的內存空間&#xff0c;它可以看作是當前線程所執行的字節碼的行號指示器&#xff0c;用于記錄正在執行的虛擬機字節碼指令的地址。Java虛擬機…

git clone的時候出現出現error

報錯如下&#xff1a; Collecting githttps://github.com/haotian-liu/LLaVA.git Cloning https://github.com/haotian-liu/LLaVA.git to /tmp/pip-req-build-360q6tt1 Running command git clone --filterblob:none --quiet https://github.com/haotian-liu/LLaVA.git /t…

Minio搭建并在SpringBoot中使用完成用戶頭像的上傳

Minio使用搭建并上傳用戶頭像到服務器操作,學習筆記 Minio介紹 minio官網 MinIO是一個開源的分布式對象存儲服務器&#xff0c;支持S3協議并且可以在多節點上實現數據的高可用和容錯。它采用Go語言開發&#xff0c;擁有輕量級、高性能、易部署等特點&#xff0c;并且可以自由…

vue3中ref和reactive響應式數據、ref模板引用(組合式和選項式區別)、組件ref的使用

目錄 Ⅰ.ref 1.基本用法&#xff1a;ref響應式數據 2.ref模板引用 3.ref在v-for中的模板引用 ?4.ref在組件上使用 ?5.TS中ref數據標注類型 Ⅱ.reactive 1.基本用法&#xff1a;reactive響應式數據 2.TS中reactive標注類型 Ⅲ.ref和reactive的使用場景和區別 Ⅳ.小結…

javascript實現雪花飄落效果

本文實現雪花飄落效果的 JavaScript 網頁設計案例&#xff0c;代碼實現如下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, init…

項目準備(flask+pyhon+MachineLearning)- 3

目錄 1.商品信息 2. 商品銷售預測 2.1 機器學習 2.2 預測功能 3. 模型評估 1.商品信息 app.route(/products) def products():"""商品分析頁面"""data load_data()# 計算當前期間和上期間current_period data[data[成交時間] > data[成…

FPGA開發,使用Deepseek V3還是R1(3):系統級與RTL級

以下都是Deepseek生成的答案 FPGA開發&#xff0c;使用Deepseek V3還是R1&#xff08;1&#xff09;&#xff1a;應用場景 FPGA開發&#xff0c;使用Deepseek V3還是R1&#xff08;2&#xff09;&#xff1a;V3和R1的區別 FPGA開發&#xff0c;使用Deepseek V3還是R1&#x…

實現 Leaflet 多類型點位標記與聚合功能的實戰經驗分享

在現代的地理信息系統&#xff08;GIS&#xff09;應用中&#xff0c;地圖功能是不可或缺的一部分。無論是展示商業網點、旅游景點還是公共服務設施&#xff0c;地圖都能以直觀的方式呈現數據。然而&#xff0c;當數據量較大時&#xff0c;地圖上可能會出現大量的標記點&#x…

企微審批中MySQL字段TEXT類型被截斷的排查與修復實踐

在MySQL中&#xff0c;TEXT類型字段常用于存儲較大的文本數據&#xff0c;但在一些應用場景中&#xff0c;當文本內容較大時&#xff0c;TEXT類型字段可能無法滿足需求&#xff0c;導致數據截斷或插入失敗。為了避免這種問題&#xff0c;了解不同文本類型&#xff08;如TEXT、M…

【常見BUG】Spring Boot 和 Springfox(Swagger)版本兼容問題

???歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學習,不斷總結,共同進步,活到老學到老…

HTTP 協議的發展歷程:從 HTTP/1.0 到 HTTP/2.0

HTTP 協議的發展歷程&#xff1a;從 HTTP/1.0 到 HTTP/2.0 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本傳輸協議&#xff09;是 Web 的基礎協議&#xff0c;用于客戶端和服務器之間的通信。從 HTTP/1.0 到 HTTP/2.0&#xff0c;HTTP 協議經歷了多次重大改…

apload-lab打靶場

1.提示顯示所以關閉js 上傳<?php phpinfo(); ?>的png形式 抓包&#xff0c;將png改為php 然后放包上傳成功 2.提示說檢查數據類型 抓包 將數據類型改成 image/jpeg 上傳成功 3.提示 可以用phtml&#xff0c;php5&#xff0c;php3 4.先上傳.htaccess文件&#xff0…

金融支付行業技術側重點

1. 合規問題 第三方支付系統的平穩運營&#xff0c;嚴格遵循《非銀行支付機構監督管理條例》的各項條款是基礎與前提&#xff0c;其中第十八條的規定堪稱重中之重&#xff0c;是支付機構必須牢牢把握的關鍵準則。 第十八條明確指出&#xff0c;非銀行支付機構需構建起必要且獨…

Cherry Studio + 火山引擎 構建個人AI智能知識庫

&#x1f349;在信息化時代&#xff0c;個人知識庫的構建對于提高工作效率、知識管理和信息提取尤為重要。尤其是當這些知識庫能結合人工智能來智能化地整理、分類和管理數據時&#xff0c;效果更為顯著。我最近嘗試通過 Cherry Studio 和 火山引擎 來搭建個人智能知識庫&#…

LeetCode 2 - 兩數相加

LeetCode 2 - 兩數相加 是一道經典鏈表操作問題&#xff0c;經常作為面試中基礎題的變體被考察。掌握多種解法及其變體&#xff0c;并熟悉其核心思路和模板代碼&#xff0c;可以快速備戰相關鏈表或大數計算問題。 題目描述 給定兩個非空鏈表&#xff0c;它們代表兩個非負整數&…

Qt之QStateMachine等待

在項目中經常需要等待&#xff0c;我們模擬0-30的數&#xff0c;假如我們其中5&#xff0c; 25的數需要進行等待&#xff0c;等待用戶處理完自己事情后&#xff0c;按下按鈕繼續&#xff0c;找Qt的項目中有一個 QStateMachineqstatemmachine類提供了一個分層有限狀態機。 QSta…

elpis全棧課程學習之elpis-core學習總結

elpis全棧課程學習之elpis-core學習總結 核心原理 elpis-core是全棧框架elpis的服務端內核&#xff0c;主要應用于服務端接口的開發以及頁面的SSR渲染&#xff0c;elpis-core基于約定優于配置的原理&#xff0c;通過一系列的loader來加載對應的文件&#xff0c;大大節約用戶的…