關于緩存異常:緩存雪崩、擊穿、穿透的解決方案

前言

關于緩存異常,我們常見的有三個問題:緩存雪崩、緩存擊穿、緩存穿透。 這三個問題一旦發生,會導致大量請求直接落到數據庫層面。如果請求的并發量很大,會影響數據庫的運行,嚴重的會導致數據庫宕機。

為了避免異常帶來的損失,我們需要了解每種異常的原因以及解決方案,提高系統的可靠性。

緩存雪崩

緩存雪崩是指大量的應用請求無法在Redis緩存中進行處理,從而使得大量請求發送到數據庫層,導致數據庫壓力過大甚至宕機。

緩存雪崩的原因

第一個原因:同一時間緩存中的數據大面積過期。

具體來說,把熱點數據保存在緩存中,并且設置了過期時間,如果在某一個時刻,大量的Key同時過期,此時,應用再訪問這些數據的話,就會發生緩存缺失。然后應用就會把請求發送給數據庫,如果應用的并發請求量很大,(比如秒殺),那么數據庫的壓力也會很大,這會進一步影響到其他正常業務的請求處理。

如下圖所示:
在這里插入圖片描述
第二個原因:Redis 緩存實例發生故障宕機。

解決方案

1、解決熱點數據集中失效

針對大量數據集中失效帶來的緩存雪崩問題,可以用下面幾種方案解決:

  • 均勻過期:給熱點數據設置不同的過期時間,給每個key的失效時間加一個隨機值;
  • 設置熱點數據永不過期:不設置失效時間,有更新的話,需要更新緩存;
  • 服務降級:指服務針對不同的數據采用不同的處理方式:
    • 業務訪問的是非核心數據,直接返回預定義信息、空值或者報錯;
    • 業務訪問核心數據,則允許訪問緩存,如果緩存缺失,可以讀取數據庫。

2、解決Redis實例宕機問題

方案一: 實現服務熔斷或者請求限流機制
我們通過監測Redis以及數據庫實例所在服務器負載指標,如果發現Redis服務宕機,導致數據庫的負載壓力增大,我們可以啟動服務熔斷機制,暫停對緩存服務的訪問。

但是這種方法對業務應用的影響比較大,我們也可以通過限流的方式降低這種影響。

舉個例子:比如業務系統正常運行時,請求入口每秒最大允許進入的請求數是1萬個,其中9000請求個可以被緩存處理,余下1000個會發送給數據庫處理。

一旦發生雪崩,數據庫每秒處理的請求突然增加到1萬個,此時我們就可以啟動限流機制。在前端請求入口處,只允許每秒進入1000個請求,其他的直接拒絕掉。這樣就可以避免大量并發請求發送給數據庫。

方案二:事前預防
通過主從節點的方式構建 Redis 緩存高可靠集群。 如果 Redis 緩存的主節點故障宕機了,從節點還可以切換成為主節點,繼續提供緩存服務,避免了由于緩存實例宕機而導致的緩存雪崩問題。

緩存擊穿

緩存擊穿和緩存雪崩有點像,但是也有一點區別。

緩存雪崩是因為大面積的緩存失效,打崩了數據庫。而緩存擊穿是指某個訪問非常頻繁的熱點數據,大量并發請求集中在這一個點訪問,在這個Key失效的瞬間,持續的大并發就穿破緩存,直接請求數據庫,就像在一個屏障上鑿了一個洞。

解決方案

  1. 設置熱點數據永不過期:不設置失效時間,有更新的話,需要更新緩存;
  2. 加互斥鎖:單機可以使用synchronizedlock,分布式可以使用lua腳本。

關于分布式鎖有興趣的同學可以看下這篇:Redis分布式鎖的正確打開方式

緩存穿透

緩存穿透指用戶要訪問的數據既不在緩存中也不在數據庫中,導致用戶每次請求該數據時都要去數據庫查一遍,然后返回空。

如果有惡意攻擊者不斷請求這種系統不存在的數據,會導致數據庫壓力過大,嚴重會擊垮數據庫。

解決方案

  • 接口層增加校驗:用戶鑒權、參數校驗(請求參數是否合法、請求字段是否不存在等等);
  • 緩存空值/缺省值:發生緩存穿透時,我們可以在Redis中緩存一個空值或者缺省值(例如,庫存缺省值為0),這樣就避免了把大量請求發送給數據庫處理,保持了數據庫的正常運行。這種方法會存在兩個問題:
    • 如果有大量的Key穿透,緩存空對象會占用寶貴的內存空間。針對這種情況可以給空對象設置過期時間。
    • 設置過期時間之后,可能會有緩存與數據庫不一致的情況。
  • 布隆過濾器:快速判斷數據是否存在,避免從數據庫中查詢數據是否存在,減輕數據庫壓力。

前面兩種方案比較好實現,接下面我們介紹下布隆過濾器。

布隆過濾器

布隆過濾器(Bloom Filter)是1970年由布隆提出的。它實際上是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器可以用于檢索一個元素是否在一個集合中。

  • 優點:空間效率和查詢時間都遠遠超過一般的算法。
  • 缺點:有一定的誤識別率,刪除困難。

布隆過濾器原理

布隆過濾器本質上是一個初始值都為 0 的 二進制數組和 N 個哈希函數組成

當我們想標記某個數據存在時(例如,數據x已被寫入數據庫),布隆過濾器會通過三個操作完成標記:

  • 首先,使用 N 個哈希函數,分別計算這個數據的哈希值,得到 N 個哈希值。
  • 然后,我們把這 N 個哈希值對 bit 數組的長度取模,得到每個哈希值在數組中的對應位置。
  • 最后,我們把對應位置的 bit 位設置為 1,這就完成了在布隆過濾器中標記數據的操作。

如下圖所示:
在這里插入圖片描述

三次哈希,對應的二進制數組下標分別是 1、3、7,將原始數據從 0 變為 1。

同樣的,我們標記數據y的邏輯也是一樣的。如下圖:
在這里插入圖片描述

三次哈希,對應的二進制數組下標分別是 1、5、9,將原始數據從 0 變為 1。

下標 1,之前已經被操作設置成 1,則本次認為是哈希沖突,不需要改動。

Hash 規則:如果在 Hash 后,原始位它是 0 的話,將其從 0 變為 1;如果本身這一位就是 1 的話,則保持不變。

正是因為存在哈希沖突,導致布隆過濾器的判斷存在誤差

因為哈希沖突的存在,導致布隆過濾器不能輕易刪除數據,存在誤刪的風險。

布隆過濾器減少誤差的方法:

  • 增加二進制位數組的長度,這樣hash后的數據會更加離散化,出現沖突的概率會大大降低;
  • 增加Hash的次數,變相的增加數據特征,特征越多,沖突的概率越小。

布隆過濾器如何使用

比如,當查詢一件商品的緩存信息時,我們首先要判斷這件商品是否存在。

  • 通過三個哈希函數對商品id計算哈希值;
  • 然后,在布隆數組中查找訪問對應的位值,0或1;
  • 判斷,三個值中,只要有一個不是1,那么我們認為數據是不存在的。

如下圖:
在這里插入圖片描述
注意:布隆過濾器只能精確判斷數據不存在情況,對于存在我們只能說是可能,因為存在Hash沖突情況,當然這個概率非常低。

在Java中使用布隆過濾器

至于在Java應用中使用布隆過濾器,我們可以通過Redisson實現,它內置了布隆過濾器。

首先引入依賴:

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.15.0</version>
</dependency>

代碼示例:

import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;public class RedissonBloomFilter {public static void main(String[] args) {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");RedissonClient client = Redisson.create(config);RBloomFilter<String> bloomFilter = client.getBloomFilter("test-bloom-filter");// 初始化布隆過濾器,數組長度100W,誤判率 1%bloomFilter.tryInit(1000000L, 0.01);// 添加數據bloomFilter.add("Shawn");// 判斷是否存在System.out.println(bloomFilter.contains("xujunson"));System.out.println(bloomFilter.contains("Shawn"));}
}

運行結果:

false   // 肯定不存在
true    // 可能存在,有1%的誤判率

好了,以上就是關于緩存異常的整理。跟緩存雪崩、緩存擊穿這兩類問題相比,緩存穿透的影響更大一些,需要重點關注一下。


---------------------
作者:徐俊生
來源:CSDN
原文:https://blog.csdn.net/D812359/article/details/120648158
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件

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

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

相關文章

RobotFramework 自動化測試實戰進階篇

工具 Robotframework, 采用PO設計模式 PO模型 PO模型即Page Objects&#xff0c;直譯意思就是“頁面對象”&#xff0c;通俗的講就是把一個頁面&#xff0c;或者說把一個頁面的某個區域當做一個對象&#xff0c;通過封裝這個對象可以實現調用。 PO設計的好處 代碼復用&…

Android6 0權限機制(一):介紹

本篇文章已授權微信公眾號 hongyangAndroid &#xff08;鴻洋&#xff09;獨家發布 Android6.0權限機制&#xff08;一&#xff09;&#xff1a;介紹 Android6.0權限機制&#xff08;二&#xff09;&#xff1a;封裝 Android6.0權限機制&#xff08;三&#xff09;&#xff1a;…

MAX10 ADC的一些基知識

MAX10 ADC 的一些知識 1、 MAX 10 內部集成的12bit SAR ADC的特點為&#xff1a; a、 采樣速率高達1Mhz. b、 模擬通道多達18個&#xff0c;單個ADC多達17個&#xff0c;雙ADC器件中有16個雙功能ADC通道&#xff0c;2個專用的ADC。 c、 提供單端測…

Blazor University (42)JavaScript 互操作 —— 生命周期和內存泄漏

原文鏈接&#xff1a;https://blazor-university.com/javascript-interop/calling-dotnet-from-javascript/lifetimes-and-memory-leaks/生命周期和內存泄漏源代碼[1]如果我們運行我們在從 Javascript 調用 .NET 中創建的應用程序并檢查瀏覽器控制臺窗口&#xff0c;我們會看到…

深入淺出聊布隆過濾器(Bloom Filter)

之前在網上看到過這么一段話&#x1f447; Data structures are nothing different. They are like the bookshelves of your application where you can organize your data. Different data structures will give you different facility and benefits. To properly use the …

第五周作業

本周作業內容&#xff1a;顯示當前系統上root、fedora或user1用戶的默認shell&#xff1b;#egrep "^(root|user1|fedora)" /etc/passwd|cut -d: -f72、找出/etc/rc.d/init.d/functions文件中某單詞后面跟一組小括號的行&#xff0c;形如&#xff1a;hello()&#xff…

我為什么卸載了今日頭條

曾經的自媒體人自述。 兩三年前自媒體熱曾席卷中國互聯網&#xff0c;當時短視頻還不是很火&#xff0c;一般的自媒體人都是以撰寫文章為主&#xff0c;各種微信公眾號層出不窮&#xff0c;10W的俗稱 爆文&#xff08;豹紋&#xff09;。后來以今日頭條為領頭的短視頻自媒體出現…

appium執行iOS測試腳本并發問題

appium1.4.XiOS9.Xxcode7.X: appium1.4.xiOS9.xxcode7.x&#xff0c;這一整套的配置做移動端自動化測試是測試人員常用的測試框架。關于&#xff0c;這一套測試框架的并發問題&#xff1a;基于mac端&#xff0c;啟動多臺appium服務器會導致appium的運行出錯。這是因為多個appiu…

WinForm(五)控件和它的成員

窗體無疑是WinForm的主角&#xff0c;每個窗體都是用一個class來承載&#xff0c;那么窗體的控件&#xff0c;就是類中的私有字段了。每個窗體有三個文件&#xff0c;兩個.cs文件&#xff0c;是一個分部類&#xff0c;Designer.cs是自動生成的C#代碼&#xff0c;一般是拖拽控件…

Atitit.異常處理 嵌套??冗長的解決方案

Atitit.異常處理 嵌套 冗長的解決方案 1. 異常處理的需要改進的地方1 2. 異常設計的初衷是, 在程序中出現錯誤時, 由程序自己處理錯誤, 盡量不要以exit(0)這種粗暴的方式中止程序. 1 3. 正常流程和異常流程的分離。2 4. “是藥三分毒”&#xff0c; 任何事物有缺點&#xff0c…

一文詳解|增長那些事兒

目錄 增長的背景 1.1 增長的定義 1.2 如何判斷事物是否在增長 1.3 如何判斷事物能否持續增長 如何進行增長 2.1 尋找增長機會點&#xff08;人的能力&#xff09; 2.1.1 發散與收劍找機會點 2.1.2 實驗分析驗證 2.1.3 增長洞察提取策略 2.1.4 如何找到大機會 2.2 設…

在MVC項目中使用Ninject

項目結構圖&#xff1a; App_start文件夾中的文件是VS自己創建的&#xff0c;其中NinjectWebCommon類在創建之初并不存在。后面會再次提到&#xff01; 添加一個Home控制器。代碼如下&#xff1a; using EssentialTools.Models; using Ninject; using System; using System.Col…

linux IP、端口連通性測試

ssh -v -p 50001 root10.210.200.82轉載于:https://www.cnblogs.com/kuiyeit/p/6723508.html

緊急通知:360 網站衛士前端公共庫已停止服務

所有使用了360前端公共庫的開發者和站長們&#xff0c;請及時更換你的前端庫的鏈接&#xff08;主要是前端庫和谷歌 fonts&#xff09;&#xff0c;否則網站打開速度會極慢&#xff0c;甚至會在 Chrome 瀏覽器中崩潰。 360前端公共庫曾經提供的服務有&#xff1a; 前端公共庫&a…

一文學會Autofac的基礎操作:幾種實現注冊方式、3種注入方式、生命周期、AOP以及過濾器實現依賴注入...

前言&#xff1a;直接開干。使用Autofac進行服務注冊實踐&#xff1a;新建三個項目&#xff0c;分別是webapi項目 Wesky.Core.Autofac以及兩個類庫項目 Wesky.Core.Interface和Wesky.Core.Service。在Webapi項目下&#xff0c;引用Autofac的三個包&#xff1a;Autofac、Autofac…

解析互聯網廣告術語 CPM、CPC、CPA、CPS、CPL、CPR 是什么意思

1. CPM&#xff08;Cost per mille&#xff09;&#xff0c;每千次展現收費 這是一種最為常見的廣告模式&#xff0c;也是很多網站流量變現的一種途徑&#xff0c;這種廣告不管計算點擊&#xff0c;或者什么注冊下載之類的轉化&#xff0c;只要這個廣告在網站上被正常的展現給…

JavaScript數組迭代方法(圖解)

轉載于:https://www.cnblogs.com/seanna/p/6724032.html

Rider調試ASP.NET Core時報thread not gc-safe的解決方法

新建了一個ASP.NET Core 5.0的Web API項目&#xff0c;當使用斷點調試Host.CreateDefaultBuilder(args)時&#xff0c;進入該函數后查看中間變量的值&#xff0c;報錯Evaluation is not allowed: The thread is not at a GC-safe point。在群里問了也沒人回應&#xff0c;可能沒…

The SDK platform-tools version ((23)) is too old to check APIs compiled with API 26;

好像是更新過啥SDK之后&#xff0c;項目一直在包名的那一行顯示紅線&#xff0c;不過是不報編譯錯誤的&#xff0c;就是看著老扎心老扎心的&#xff0c;開始以為是指定的SDK版本的問題&#xff0c;修改后發現無效&#xff0c;最后找到方法解決&#xff1a; 打開SDK Manager ---…

oracle 各種日期函數格式和操作

2019獨角獸企業重金招聘Python工程師標準>>> ORACLE日期時間函數大全 TO_DATE格式(以時間:2007-11-02 13:45:25為例) Year: yy two digits 兩位年 顯示值:07 yyy three digits 三位年 顯示值:00…