成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一個(gè) Redis 的雪崩和穿透問(wèn)題,小學(xué)妹畫(huà)了個(gè)圖,結(jié)果入職了

存儲(chǔ) 存儲(chǔ)軟件 Redis
字符串 "Java" 在經(jīng)過(guò)四個(gè)映射函數(shù)操作后在位圖上有四個(gè)點(diǎn)被設(shè)置成了 1。當(dāng)我們需要判斷 “ziyou” 字符串是否存在的時(shí)候只要在一次對(duì)字符串進(jìn)行映射函數(shù)的操作,得到四個(gè) 1 就說(shuō)明 “Java” 是可能存在的。

[[409025]]

本文轉(zhuǎn)載自微信公眾號(hào)「Java極客技術(shù)」,作者鴨血粉絲。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java極客技術(shù)公眾號(hào)。

阿粉的一個(gè)小學(xué)妹最近剛從某個(gè)小互聯(lián)網(wǎng)公司跳槽,然后最近面試的挺多的,一個(gè)不善言語(yǔ)的小姑娘,技術(shù)還是 OK 的,本來(lái)之前是做 UI 的,但是時(shí)間長(zhǎng)了,感覺(jué)沒(méi)太大意思,所以就開(kāi)始學(xué)了后端,然后從原有公司慢慢的轉(zhuǎn)為了后端開(kāi)發(fā)人,也就是我們所說(shuō)的 “程序猿”,最近面試給阿粉談了談她的面試經(jīng)驗(yàn)。阿粉比較印象深刻的一句話就是,我給你畫(huà)個(gè)圖,你看一下,這是對(duì)面試官說(shuō)的,事情是什么樣子的呢?

你了解 Redis 穿透和雪崩么?

為什么這么說(shuō),因?yàn)槊嬖嚬佼?dāng)你說(shuō)到 Redis 的時(shí)候,面試官問(wèn)的現(xiàn)在已經(jīng)不是 "你說(shuō)一下 Redis 的幾種數(shù)據(jù)結(jié)構(gòu)" ,現(xiàn)在面試問(wèn)的時(shí)候,很多都是對(duì) Redis 的實(shí)際使用開(kāi)始問(wèn)了,比如說(shuō),

  • Redis 都有哪些架構(gòu)模式?單機(jī)版,主從復(fù)制,哨兵機(jī)制,集群(proxy 型),集群(直連型)
  • 使用過(guò) Redis 分布式鎖么,它是怎么實(shí)現(xiàn)的?
  • 使用過(guò) Redis 做異步隊(duì)列么,你是怎么用的?有什么缺點(diǎn)?
  • 什么是緩存穿透?如何避免?什么是緩存雪崩?何如避免?

而阿粉的小學(xué)妹遇到的就是關(guān)于 Redis 的緩存穿透和雪崩問(wèn)題了。這個(gè)問(wèn)題學(xué)妹配合了一波自己的 UI 功底圖加上口頭的解釋,于是成功的拿到了這個(gè) Offer,也可能是因?yàn)樾W(xué)妹比較美麗并且技術(shù)還過(guò)的去。所以,就準(zhǔn)備入職了。

我們來(lái)看看小學(xué)妹到底畫(huà)了什么圖,讓面試官問(wèn)了一波之后就入職了。

緩存穿透

如圖:圖是阿粉找小學(xué)妹專門畫(huà)出來(lái)的,大家看一下

既然我們看完圖了,相信大家也都看到了什么是緩存穿透了,也就是說(shuō),在我們的緩存系統(tǒng)中,也就是 Redis 中,我們都是拿著我們的 Key 去 Redis 中去尋找 Value 中,如果說(shuō)我們?cè)?Redis 中找不到我們的數(shù)據(jù)之后,我們就會(huì)去數(shù)據(jù)庫(kù)中去尋找我們的數(shù)據(jù),如果只是單一請(qǐng)求的話,也不能算是個(gè)太大的問(wèn)題,只能稱之為擊穿而已,但是如果說(shuō)要是請(qǐng)求并發(fā)量很大的話,就會(huì)對(duì)我們的數(shù)據(jù)庫(kù)造成很大的壓力,這其實(shí)就稱之為緩存穿透,而穿透出現(xiàn)的嚴(yán)重后果,就會(huì)是緩存的雪崩了,我們先說(shuō)穿透,一會(huì)再說(shuō)雪崩。

那么都會(huì)有什么情況會(huì)造成緩存被穿透呢?

  • 自身代碼問(wèn)題
  • 一些惡意攻擊、爬蟲(chóng)造成大量空的命中。

如果有個(gè)黑客對(duì)你們公司的項(xiàng)目和數(shù)據(jù)庫(kù)比較感興趣,他就可能會(huì)給你整出巨多的一些不存在的ID,然后就瘋狂的去調(diào)用你們的某項(xiàng)接口,這些本身不存在的 ID 去查詢緩存的數(shù)據(jù)的時(shí)候,那就是壓根沒(méi)有的,這時(shí)候就會(huì)有大量的請(qǐng)求去訪問(wèn)數(shù)據(jù)庫(kù),雖然可能數(shù)據(jù)能支撐一段時(shí)間,但是早晚會(huì)讓人家給你整的涼了。

那么應(yīng)該怎么去解決緩存穿透的問(wèn)題呢?

  • 利用互斥鎖,緩存失效的時(shí)候,先去獲得鎖,得到鎖了,再去請(qǐng)求數(shù)據(jù)庫(kù)。沒(méi)得到鎖,則休眠一段時(shí)間重試。
  • 采用異步更新策略,無(wú)論 Key 是否取到值,都直接返回。Value 值中維護(hù)一個(gè)緩存失效時(shí)間,緩存如果過(guò)期,異步起一個(gè)線程去讀數(shù)據(jù)庫(kù),更新緩存。需要做緩存預(yù)熱(項(xiàng)目啟動(dòng)前,先加載緩存)操作。
  • 提供一個(gè)能迅速判斷請(qǐng)求是否有效的攔截機(jī)制,比如,利用布隆過(guò)濾器,內(nèi)部維護(hù)一系列合法有效的 Key。迅速判斷出,請(qǐng)求所攜帶的 Key 是否合法有效。如果不合法,則直接返回。
  • 布隆過(guò)濾器實(shí)際上是一種比較推薦的方式。

布隆過(guò)濾器的實(shí)現(xiàn)原理則是這樣的:

當(dāng)一個(gè)變量被加入集合時(shí),通過(guò) K 個(gè)映射函數(shù)將這個(gè)變量映射成位圖中的 K 個(gè)點(diǎn),把它們置為 1。查詢某個(gè)變量的時(shí)候我們只要看看這些點(diǎn)是不是都是 1 就可以大概率知道集合中有沒(méi)有它了,如果這些點(diǎn)有任何一個(gè) 0,則被查詢變量一定不在;如果都是 1,則被查詢變量很可能在。注意,這里是可能存在,不一定一定存在!這就是布隆過(guò)濾器的基本思想。

而當(dāng)你說(shuō)出布隆過(guò)濾器的時(shí)候,可能這才是面試官想要問(wèn)你的內(nèi)容,這時(shí)候你就得好好的和面試官開(kāi)始聊聊什么事布隆過(guò)濾器了。

我們還是繼續(xù)用大眾都想看到的圖解來(lái)解釋布隆過(guò)濾器。

字符串 "Java" 在經(jīng)過(guò)四個(gè)映射函數(shù)操作后在位圖上有四個(gè)點(diǎn)被設(shè)置成了 1。當(dāng)我們需要判斷 “ziyou” 字符串是否存在的時(shí)候只要在一次對(duì)字符串進(jìn)行映射函數(shù)的操作,得到四個(gè) 1 就說(shuō)明 “Java” 是可能存在的。

注意語(yǔ)言,是可能存在,而不是一定存在,

那是因?yàn)橛成浜瘮?shù)本身就是散列函數(shù),散列函數(shù)是會(huì)有碰撞的,意思也就是說(shuō)會(huì)存在一個(gè)字符串可能是 “Java1” 經(jīng)過(guò)相同的四個(gè)映射函數(shù)運(yùn)算得到的四個(gè)點(diǎn)跟 “Java” 可能是一樣的,這種情況下我們就說(shuō)出現(xiàn)了誤算。

另外還有可能這四個(gè)點(diǎn)位上的 1 是四個(gè)不同的變量經(jīng)過(guò)運(yùn)算后得到的,這也不能證明字符串 “Java” 是一定存在的。

而我們使用布隆過(guò)濾器其實(shí)就是提供一個(gè)能迅速判斷請(qǐng)求是否有效的攔截機(jī)制,判斷出請(qǐng)求所攜帶的 Key 是否合法有效。如果不合法,則直接返回。

而阿粉的小學(xué)妹給面試官解釋了一波這操作之后,看樣子,面試官對(duì)這個(gè)“程序猿”開(kāi)始有點(diǎn)印象了,接下來(lái)就順著問(wèn)了,那什么事緩存的雪崩呢?

緩存雪崩

這時(shí)候也就是說(shuō),當(dāng)我們有多個(gè)請(qǐng)求訪問(wèn)緩存的時(shí)候,這時(shí)候,緩存中的數(shù)據(jù)是沒(méi)有的,也就是說(shuō)緩存同一時(shí)間大面積的失效,這個(gè)時(shí)候又來(lái)了一波請(qǐng)求,結(jié)果請(qǐng)求都懟到數(shù)據(jù)庫(kù)上,從而導(dǎo)致數(shù)據(jù)庫(kù)連接異常

他和穿透實(shí)際上相似但是又有所不同,相似的地方是都是搞數(shù)據(jù)庫(kù),不同的是緩存穿透是指并發(fā)查同一條數(shù)據(jù),緩存雪崩是不同數(shù)據(jù)都過(guò)期了,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫(kù)

而解決緩存雪崩的策略也是比較多的,而且都是比較實(shí)用的。比如:

  • 給緩存的失效時(shí)間,加上一個(gè)隨機(jī)值,避免集體失效。
  • 雙緩存。我們有兩個(gè)緩存,緩存 A 和緩存 B。緩存 A 的失效時(shí)間為 20 分鐘,緩存 B 不設(shè)失效時(shí)間

雙緩存策略比較有意思,當(dāng)請(qǐng)求來(lái)臨的時(shí)候,我們先從 A 緩存中獲取,如果 A 緩存有數(shù)據(jù),那么直接給他返回,如果 A 中沒(méi)有數(shù)據(jù),那么就直接從 B 中獲取數(shù)據(jù),直接返回,與此同時(shí),我們啟動(dòng)一個(gè)更新的線程,更新 A 緩存和 B 緩存,這就是雙緩存的策略。

上述的處理緩存雪崩的情況實(shí)際上都是從代碼上來(lái)進(jìn)行實(shí)現(xiàn),而我們換個(gè)思路考慮呢,也就是從架構(gòu)的方向去考慮的話,解決方案就是以下的幾種了。

  • 限流
  • 降級(jí)
  • 熔斷

那么怎么實(shí)現(xiàn)限流呢?

說(shuō)到限流降級(jí)了,那就不能單純的去針對(duì) Redis 出現(xiàn)的問(wèn)題而進(jìn)行處理了,而實(shí)際上是為了保證用戶保護(hù)服務(wù)的穩(wěn)定性來(lái)進(jìn)行的。

那么為什么要去限流呢?你要單純的說(shuō)是為了保證系統(tǒng)的穩(wěn)定性,那面試官估計(jì)得崩潰,這和沒(méi)說(shuō)有啥區(qū)別,你得舉個(gè)簡(jiǎn)單的例子才能正兒八經(jīng)的忽悠住面試官,比如:

假設(shè),我們當(dāng)前的程序能夠處理10個(gè)請(qǐng)求,結(jié)果第二天,忽然有200多請(qǐng)求一起過(guò)來(lái),整整翻了20倍,這時(shí)候,程序就涼了,但是如果第一天晚上的時(shí)候,領(lǐng)導(dǎo)給你說(shuō),明天你寫(xiě)的那個(gè)程序大約會(huì)有200多個(gè)請(qǐng)求要處理,你這時(shí)候是不是得想辦法,比如說(shuō),能不能再寫(xiě)出另外的一段程序來(lái)進(jìn)行分擔(dān)請(qǐng)求,這時(shí)候其實(shí)就相當(dāng)于需要我們?nèi)ハ蘖髁恕?/p>

限流算法之漏桶算法

同樣的,我們整個(gè)圖來(lái)理解一下這個(gè)算法到底是怎么實(shí)現(xiàn)的。

如果一桶有一個(gè)細(xì)眼,我們往里面裝水,可以看到水是一滴一滴勻速的下落的,如果桶滿了就拒絕水滴繼續(xù)滴入,沒(méi)滿的話就繼續(xù)裝水,實(shí)際上就是這樣的水滴實(shí)際上就相當(dāng)于是請(qǐng)求,如果水桶沒(méi)滿的時(shí)候,還能繼續(xù)處理我們進(jìn)來(lái)的請(qǐng)求,當(dāng)水桶滿了的時(shí)候,就拒絕處理,讓他溢出。

前提是我們的這個(gè)桶是個(gè)固定的容器,不能隨著水的增多桶會(huì)變大,要不然那還用什么限流算法。

簡(jiǎn)單的漏桶算法的實(shí)現(xiàn):

  1. public class LeakyBucket { 
  2.         public long timeStamp = System.currentTimeMillis();  // 當(dāng)前時(shí)間 
  3.         public long capacity; // 桶的容量 
  4.         public long rate; // 水漏出的速度 
  5.         public long water; // 當(dāng)前水量(當(dāng)前累積請(qǐng)求數(shù)) 
  6.  
  7.         public boolean grant() { 
  8.             long now = System.currentTimeMillis(); 
  9.             // 先執(zhí)行漏水,計(jì)算剩余水量 
  10.             water = Math.max(0, water - (now - timeStamp) * rate);  
  11.              
  12.             timeStamp = now; 
  13.             if ((water + 1) < capacity) { 
  14.                 // 嘗試加水,并且水還未滿 
  15.                 water += 1; 
  16.                 return true
  17.             } else { 
  18.                 // 水滿,拒絕加水 
  19.                 return false
  20.         } 
  21.     } 

上面的代碼是來(lái)自悟空,不得不說(shuō),這個(gè)簡(jiǎn)單的例子雖然簡(jiǎn)單,但是把這個(gè)漏桶算法的簡(jiǎn)單原理描述的還是差不多的,而在這里最需要注意的,就是桶的容量,還有就是水桶漏洞的出水的速度。

既然我們了解了漏桶算法是如何實(shí)現(xiàn)限流的,那么必然也會(huì)有他處理不來(lái)的情況,因?yàn)槲覀円呀?jīng)定義了水漏出的速度,而這時(shí)候如果應(yīng)對(duì)突發(fā)的流量忽然涌進(jìn)來(lái),他處理起來(lái)效率就不夠高了,因?yàn)樗皾M了之后,請(qǐng)求都拒絕了,都不處理了。

其實(shí)我們所說(shuō)的漏桶算法還可以看作是一個(gè)帶有常量服務(wù)時(shí)間的單服務(wù)器隊(duì)列,如果漏桶(包緩存)溢出,那么數(shù)據(jù)包會(huì)被丟棄。

而我們的漏桶算法主要是能夠強(qiáng)行限制數(shù)據(jù)的傳輸速率。

那么又有什么算法能夠不進(jìn)行強(qiáng)制限制傳輸速率,并且實(shí)現(xiàn)限流呢?

令牌桶算法

我們感謝百度,我從百度圖片中找了個(gè)一個(gè)比較給力的圖來(lái)描述令牌桶的算法。

令牌桶算法的基本過(guò)程是這個(gè)樣子的:

  1. 用戶配置的平均發(fā)送速率為r,則每隔1/r秒一個(gè)令牌被加入到桶中
  2. 假設(shè)桶最多可以存發(fā)b個(gè)令牌。如果令牌到達(dá)時(shí)令牌桶已經(jīng)滿了,那么這個(gè)令牌會(huì)被丟棄
  3. 當(dāng)一個(gè)n個(gè)字節(jié)的數(shù)據(jù)包到達(dá)時(shí),就從令牌桶中刪除n個(gè)令牌,并且數(shù)據(jù)包被發(fā)送到網(wǎng)絡(luò)
  4. 如果令牌桶中少于n個(gè)令牌,那么不會(huì)刪除令牌,并且認(rèn)為這個(gè)數(shù)據(jù)包在流量限制之外

乍一看,怎么感覺(jué)這個(gè)令牌桶和漏桶這么像,一個(gè)是水滴,一個(gè)是令牌,實(shí)際上不是。

令牌桶這種控制機(jī)制基于令牌桶中是否存在令牌來(lái)指示什么時(shí)候可以發(fā)送流量。令牌桶中的每一個(gè)令牌都代表一個(gè)字節(jié)。如果令牌桶中存在令牌,則允許發(fā)送流量;而如果令牌桶中不存在令牌,則不允許發(fā)送流量。

而且他是能夠應(yīng)對(duì)突發(fā)限制的,雖然傳輸?shù)乃俾适艿搅讼拗?所以它適合于具有突發(fā)特性的流量的一種算法。

而在 Google 開(kāi)源工具包中的限流工具類RateLimiter ,這個(gè)類就是根據(jù)令牌桶算法來(lái)完成限流。大家有興趣的可以去看看呀。

漏桶算法和令牌桶算法的區(qū)別

漏桶算法與令牌桶算法實(shí)際上看起來(lái)有點(diǎn)相似,但是不能混淆哈,這就是阿粉在上面說(shuō)的:

漏桶算法能夠強(qiáng)行限制數(shù)據(jù)的傳輸速率。

 

令牌桶算法能夠在限制數(shù)據(jù)的平均傳輸速率的同時(shí)還允許某種程度的突發(fā)傳輸

 

責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2020-03-16 14:57:24

Redis面試雪崩

2021-03-09 17:09:42

拷貝算法對(duì)象

2019-10-12 14:19:05

Redis數(shù)據(jù)庫(kù)緩存

2023-03-10 13:33:00

緩存穿透緩存擊穿緩存雪崩

2025-02-13 07:49:18

2023-04-14 07:34:19

2025-04-29 10:28:25

2019-03-27 13:56:39

緩存雪崩穿透

2019-02-13 11:04:42

系統(tǒng)緩存軟件

2021-07-19 08:41:49

藍(lán)屏用戶Bug

2023-02-21 17:06:49

硬件軟件系統(tǒng)

2022-05-31 08:35:05

RocketMQACK客戶端

2021-12-09 11:31:16

跨域后端開(kāi)發(fā)

2024-04-18 11:43:28

緩存數(shù)據(jù)庫(kù)Redis

2024-01-19 20:42:08

Redis數(shù)據(jù)庫(kù)Key

2024-04-07 00:00:02

Redis雪崩緩存

2021-06-05 09:01:01

Redis緩存雪崩緩存穿透

2020-04-03 09:45:09

Java多線程接口

2024-05-20 01:10:00

Promise變量

2020-01-03 10:46:16

Windows 功能系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 精品久久久久久亚洲精品 | 久久婷婷国产香蕉 | 久久久精| 天天影视亚洲综合网 | 国产精品久久亚洲7777 | 国产福利视频在线观看 | 男女黄网站 | 精品中文字幕一区二区 | 在线看日韩av | 日本福利在线观看 | 欧美 日韩 视频 | 日韩精品成人av | 在线观看视频一区二区三区 | 日韩高清国产一区在线 | 久久伦理电影 | 91久久久久久久久久久久久 | 黄色片在线 | 成人国产午夜在线观看 | 久久影院一区 | 亚洲成人综合在线 | 日本中出视频 | 超碰在线人人 | 在线观看黄视频 | 中文视频在线 | 一区二区三区四区免费观看 | 中文字幕日韩一区 | 福利电影在线 | 欧美成人在线免费 | 日韩在线播放av | 中文字幕国产精品 | 91中文字幕在线观看 | 成人h视频 | 久久国产精品亚洲 | 高清久久久 | 亚洲天堂网站 | 女朋友的闺蜜3韩国三级 | 久久久xx | 国产精品1 | 日韩一区不卡 | 在线免费观看黄a | 午夜大片|