自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

老生常談的 Redis 雪崩、擊穿、穿透、預(yù)熱、降級一次全安排

開發(fā) 開發(fā)工具 Redis
關(guān)于 Redis 的介紹、特點什么的就不再這里贅述了,不然又要水千把字。今天我們就重點看企業(yè)中在使用 Redis 常見一些問題以及對應(yīng)解決方案。

 [[392423]]

關(guān)于 Redis 的介紹、特點什么的就不再這里贅述了,不然又要水千把字。今天我們就重點看企業(yè)中在使用 Redis 常見一些問題以及對應(yīng)解決方案。

某個請求到達業(yè)務(wù)系統(tǒng),想要獲取某個數(shù)據(jù),一般是先從緩存中獲取,如果緩存中不存在就會去數(shù)據(jù)庫中查詢,如果查詢到結(jié)果就將數(shù)據(jù)保存到緩存中再返回結(jié)果。

一個新的技術(shù)的引進,必然會帶來一些額外的問題,那么 Redis 這么優(yōu)秀的 NoSQL 數(shù)據(jù)庫會帶來什么樣的問題呢?我們一起拭目以待。

緩存擊穿

緩存擊穿根據(jù)名字根本無法看懂是什么意思,并且很容易和另一個詞——緩存穿透搞混。緩存擊穿指的是某個 key 一直在扛著高并發(fā),所謂扛著高并發(fā)就是說大量的請求都是獲取這個 key 對應(yīng)的值。

而這個 key 在某個時間突然失效了,那是不是就意味著大量的請求就無法在緩存中獲取數(shù)據(jù)了,而是去請求數(shù)據(jù)庫了,這樣很有可能導(dǎo)致數(shù)據(jù)庫被擊垮。這就是緩存擊穿。

那現(xiàn)在問題知道了,該如何應(yīng)對呢?這個就比較簡單了,既然這個 key 這個受歡迎,那么就不要設(shè)置過期時間了,如果該key的數(shù)據(jù)更新了,那么就通過互斥鎖的方式將其更新。

為什么要用互斥鎖的方式?如果不使用互斥鎖的方式很容易導(dǎo)致數(shù)據(jù)不一致的情況,這里為了保證緩存和數(shù)據(jù)庫的一致性,就只能犧牲一點點的效率了。

緩存雪崩

不知道各位小伙伴都是來自哪里,我們那邊有句方言叫“雪崩”,表示事情砸了的意思。這里的Redis 雪崩似乎有點異曲同工之妙。首先我們需要知道什么是 Redis雪崩,

Redis雪崩我們一般都稱為緩存雪崩,意思就是說在某個時間節(jié)點,大量的 key 失效,導(dǎo)致大量的請求從緩存中獲取不到數(shù)據(jù)而去請求數(shù)據(jù)庫。根據(jù)上面的那張圖,我們再來畫下雪崩的情況的是什么樣子的:

上面的黑色的部分表示緩存無效了,也就意味著所有的請求都需要到數(shù)據(jù)庫中去查詢數(shù)據(jù)。那這對于數(shù)據(jù)庫的壓力必然是劇增的,如果是在一線互聯(lián)網(wǎng)這樣超高并發(fā)的場景下,數(shù)據(jù)庫直接宕機。

重啟也沒有用,因為重啟了還會有巨大的流量涌進來,然后繼續(xù)被搞宕機。所以對于預(yù)防緩存雪崩這種情況的發(fā)生意義還是很大的的。

緩存雪崩解決方案之加隨機值

上面已經(jīng)詳細介紹了什么是緩存雪崩,他是怎么發(fā)生的,那如果防止緩存雪崩呢?

很簡單,因為上面剛剛說到,緩存雪崩是由于某個時間節(jié)點大量的 key 失效而導(dǎo)致的問題,那現(xiàn)在的問題不就是變成了如何防止同一個時間節(jié)點大量的 key 失效這種情況發(fā)生嗎?

最簡單的情況就是把key的過期時間分散開,也就是在設(shè)置key的過期時間的時候再加一個隨機值,就這樣就能完美的解決緩存雪崩的問題。

但是你以為我說到這里就完事了?既然是一次全安排,那么我一定不會僅僅告訴你一種解決方案就完事的。繼續(xù)看

緩存雪崩解決方案之加鎖

可能很多人看到這個方案表示不接受,加鎖那不是限制了并發(fā)?加鎖必然導(dǎo)致阻塞。如果是加鎖,那么執(zhí)行就成就是這個樣子了:

流程是這樣子的,在多個請求同時到達業(yè)務(wù)系統(tǒng)時候,只能有一個線程能獲取到鎖,然后才能繼續(xù)去緩存或者是數(shù)據(jù)庫中查詢數(shù)據(jù),然后后面的流程和之前的是一樣的,執(zhí)行完成后釋放鎖,然后其他線程再爭搶鎖,然后重復(fù)前面的流程。

這個方案的優(yōu)點是可以很好的保護數(shù)據(jù)庫不會被打掛,缺點就是并發(fā)度極低。

上面這個方案其實還是可以再優(yōu)化下的:

這個就是在緩存中如果獲取不到,再去串行的訪問數(shù)據(jù)看,這里不一定非要串行,可以配合線程池,控制一定的并發(fā)數(shù)。

這個缺點雖然很多,但是也是一種解決方案。用不用就看實際的業(yè)務(wù)場景了。畢竟沒有沒用技術(shù)方案,只有不適合業(yè)務(wù)場景的技術(shù)方案(手動狗頭)。

緩存穿透

緩存穿透意思就是某個不存在的key一直被訪問,結(jié)果發(fā)現(xiàn)數(shù)據(jù)庫中也沒有這樣的數(shù)據(jù),最終導(dǎo)致訪問該key的所有請求都直接請求到數(shù)據(jù)庫了。如果是并發(fā)高的場景下就容易搞垮數(shù)據(jù)庫。大家有沒有發(fā)現(xiàn)我們做的一些事情都是在保護“弱小的數(shù)據(jù)庫”。

那現(xiàn)在問題已經(jīng)知道了,我們該如何去解決這個問題呢?

緩存穿透解決方案之緩存空數(shù)據(jù)

啥叫緩存空數(shù)據(jù)?就是假設(shè)某個key數(shù)據(jù)并不存在,那么就存一個 NULL 就好了,但是一定不要忘記設(shè)置過期時間,因為假設(shè)id=3的記錄不存在,然后本次訪問沒有查詢到數(shù)據(jù),緩存中存的是null如果過一會兒新增了一條記錄為3的數(shù)據(jù),如果緩存不設(shè)置過期時間,那么這條數(shù)據(jù)就永遠獲取不到。

緩存穿透解決方案之布隆過濾器

布隆過濾器?這玩意到底什么意思?

布隆過濾器是一種數(shù)據(jù)結(jié)構(gòu),更準(zhǔn)確的說是一種概率型的數(shù)據(jù)結(jié)構(gòu),因為它能判斷某個元素一定不存在或者是可能存在。

就這句話,搞蒙了很多人,今天我非要把你說明白了。布隆過濾器是一個bit數(shù)組,一個很長的bit數(shù)組和一系列的hash函數(shù)構(gòu)成。先看下圖

我們現(xiàn)在來舉個例子,假設(shè)現(xiàn)在有小強和旺財兩個人,他們分別經(jīng)過三次hash得到的下標(biāo)是這樣子的(布隆過濾器不存儲元素,僅僅是為一個元素是否存在打一個標(biāo)志)

小強經(jīng)過上面的三個hash后得到的下標(biāo)分別為:2、4、5,那么該數(shù)組的2、4、5位置就會被置為1,也就是此時是這樣子的

同樣旺財經(jīng)過上面的三個hash后得到的下標(biāo)分別為:3、7、11,那么該數(shù)組的3、7、11位置就會被置為1,也就是此時是這樣子的

現(xiàn)在假設(shè)來一個 007 經(jīng)過上面的三個hash后得到的下標(biāo)分別為:11、13、15因為13、和15位置是0,所以一定可以判斷007 一定不存在。但是現(xiàn)在又來了一個

9527經(jīng)過上面的三個hash后得到的下標(biāo)分別為:2、5、7,但是你會發(fā)現(xiàn)257三個位置全部是1,那這個到底說明9527是存在還是不存在呢?

從我們上面的講解可以 9527 之前并不存在,但是由于hash沖突,但是9527的三個下標(biāo)值也剛好落在已經(jīng)被置為1的下標(biāo)位置,這就導(dǎo)致此時是無法判斷9527是否存在的。這就是布隆過濾器的原理。

要不來段代碼壓壓驚?

我們來使用 google 包下的類來測試。首先要添加依賴

  1. <dependency> 
  2.  
  3.     <groupId>com.google.guava</groupId> 
  4.  
  5.     <artifactId>guava</artifactId> 
  6.  
  7.     <version>30.1-jre</version> 
  8.  
  9. </dependency> 

 

代碼如下(詳細的解釋我已經(jīng)寫在注釋中了,這個是可以用于實際生產(chǎn)的代碼)

  1. public class BloomFilterDemo { 
  2.  
  3.     public static void main(String[] args) { 
  4.  
  5.         /** 
  6.  
  7.          * 創(chuàng)建一個插入對象為一億,誤報率為0.01%的布隆過濾器 
  8.  
  9.          * 不存在一定不存在 
  10.  
  11.          * 存在不一定存在 
  12.  
  13.          */ 
  14.  
  15.         BloomFilter&lt;CharSequence&gt; bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), 
  16.  
  17.                 100000000, 
  18.  
  19.                 0.0001); 
  20.  
  21.         bloomFilter.put("死"); 
  22.  
  23.         bloomFilter.put("磕"); 
  24.  
  25.         bloomFilter.put("Redis"); 
  26.  
  27.         System.out.println(bloomFilter.mightContain("Redis")); 
  28.  
  29.         System.out.println(bloomFilter.mightContain("死")); 
  30.  
  31.         System.out.println(bloomFilter.mightContain("磕")); 
  32.  
  33.         System.out.println(bloomFilter.mightContain("Java")); 
  34.  
  35.     } 
  36.  

結(jié)果

完。

等等……緩存穿透、預(yù)熱、降級你還沒說呢。哦,我真的以為本文結(jié)束了。

那布隆過濾器是如何解決緩存穿透的問題的呢?既然已經(jīng)知道了布隆過濾器的原理,那么就可以通過布隆過濾器來快速的判斷出一個key是否存在數(shù)據(jù)庫中,如果可能存在再去數(shù)據(jù)庫查詢,如果布隆過濾器中不存在那么就需要再去數(shù)據(jù)庫查詢了。

緩存預(yù)熱

這又是什么鬼?怎么搞一個緩存還有這么多問題,那還要緩存干啥?

所謂緩存預(yù)熱就是將一些可能經(jīng)常使用數(shù)據(jù)在系統(tǒng)啟動的時候預(yù)先設(shè)置到緩存中,這樣可以避免在使用到的時候先去數(shù)據(jù)庫中查詢。

這就是緩存預(yù)熱,名氣高大上,實際上很簡單有木有,這個緩存預(yù)熱我在實際場景是經(jīng)常使用的。

還有一種方式就是添加一個緩存刷新頁,這樣通過人工干預(yù)的方式將一些可能為熱點的key添加到緩存中。

緩存降級

當(dāng)訪問量突然劇增(例如下班的點,大家都在地鐵上刷手機呢)、服務(wù)出現(xiàn)問題(如響應(yīng)時間慢或不響應(yīng))或非核心服務(wù)影響到核心流程的性能時,仍然需要保證服務(wù)還是可用的,即使是有損服務(wù)。

系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進行自動降級,降級的最終目的是保證核心服務(wù)可用,即使是有損的。但是有的一些業(yè)務(wù)的核心服務(wù)是不能降級的。這是一種丟卒保帥的思想。

結(jié)束語

關(guān)于技術(shù)的學(xué)習(xí),大家除了為了應(yīng)付面試去短期強行的記憶一些知識點外,我還是建議各位在學(xué)習(xí)階段能夠循序漸進。小孩子從出生到走路一般還有10個月呢,要想會說話時間就更長。

但是這個過程必須是有的,因為小孩子需要一點一點來適應(yīng)這個未知的世界。我們作為成年人在學(xué)習(xí)的時候也要保持這種平靜心態(tài),有些事情急是沒用的。

 

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2021-04-12 09:58:46

Redis數(shù)據(jù)庫代碼

2024-04-07 00:00:02

Redis雪崩緩存

2020-03-16 14:57:24

Redis面試雪崩

2015-06-25 10:46:23

數(shù)據(jù)中心節(jié)能

2015-07-21 13:39:58

Javascript作用域

2015-04-08 11:50:07

數(shù)據(jù)加密數(shù)據(jù)泄露

2023-03-10 13:33:00

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

2019-10-12 14:19:05

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

2022-03-08 15:01:48

負載均衡IP服務(wù)器

2014-07-25 13:34:08

2014-08-21 10:25:44

網(wǎng)絡(luò)安全兒童賬戶Google

2011-08-18 14:47:06

2010-07-28 09:09:55

SQL

2012-02-13 09:46:56

數(shù)據(jù)中心耗能服務(wù)器虛擬化

2023-04-14 07:34:19

2024-04-18 11:43:28

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

2021-06-05 09:01:01

Redis緩存雪崩緩存穿透

2024-01-19 20:42:08

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

2022-11-18 14:34:28

2022-03-08 00:07:51

緩存雪崩數(shù)據(jù)庫
點贊
收藏

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