**redis
緩存雪崩:若是緩存集中在一段時間內失效,發生大量的緩存穿透,全部的查詢都落在數據庫上,形成了緩存雪崩。
這個沒有完美解決辦法,但能夠分析用戶行爲,儘可能讓失效時間點均勻分佈。大多數系統設計者考慮用加鎖或者隊列的方式保證緩存的單線程(進程)寫,從而避免失效時大量的併發請求落到底層存儲系統上。
**緩存雪崩產生的緣由數據庫
緩存雪崩通俗簡單的理解就是:因爲原有緩存失效(或者數據未加載到緩存中),新緩存未到期間(緩存正常從Redis中獲取,以下圖)全部本來應該訪問緩存的請求都去查詢數據庫了,而對數據庫CPU和內存形成巨大壓力,嚴重的會形成數據庫宕機,形成系統的崩潰。緩存
緩存失效的時候以下圖:服務器
緩存失效時的雪崩效應對底層系統的衝擊很是可怕!那有什麼辦法來解決這個問題呢?基本解決思路以下:架構
第一,大多數系統設計者考慮用加鎖或者隊列的方式保證來保證不會有大量的線程對數據庫一次性進行讀寫,避免緩存失效時對數據庫形成太大的壓力,雖然可以在必定的程度上緩解了數據庫的壓力可是與此同時又下降了系統的吞吐量。併發
第二,分析用戶的行爲,儘可能讓緩存失效的時間均勻分佈。分佈式
第三,若是是由於某臺緩存服務器宕機,能夠考慮作主備,好比:redis主備,可是雙緩存涉及到更新事務的問題,update可能讀到髒數據,須要好好解決。高併發
解決方案spa
1:在緩存失效後,經過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。好比對某個key只容許一個線程查詢數據和寫緩存,其餘線程等待。線程
緩存失效時的雪崩效應對底層系統的衝擊很是可怕!那有什麼辦法來解決這個問題呢?基本解決思路以下:
第一,大多數系統設計者考慮用加鎖或者隊列的方式保證來保證不會有大量的線程對數據庫一次性進行讀寫,避免緩存失效時對數據庫形成太大的壓力,雖然可以在必定的程度上緩解了數據庫的壓力可是與此同時又下降了系統的吞吐量。
第二,分析用戶的行爲,儘可能讓緩存失效的時間均勻分佈。
第三,若是是由於某臺緩存服務器宕機,能夠考慮作主備,好比:redis主備,可是雙緩存涉及到更新事務的問題,update可能讀到髒數據,須要好好解決。
解決方案
1:在緩存失效後,經過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。好比對某個key只容許一個線程查詢數據和寫緩存,其餘線程等待。
注意:加鎖排隊只是爲了減輕數據庫的壓力,並無提升系統吞吐量。假設在高併發下,緩存重建期間key是鎖着的,這是過來1000個請求999個都在阻塞的。一樣會致使用戶等待超時,這是個治標不治本的方法。
2:不一樣的key,設置不一樣的過時時間,讓緩存失效的時間點儘可能均勻。
3:作二級緩存,A1爲原始緩存,A2爲拷貝緩存,A1失效時,能夠訪問A2,A1緩存失效時間設置爲短時間,A2設置爲長期
架構以下所示時候:
如何攻擊redis?
若是再redis中有1000個key,若是同一時間失效? 直接查數據庫了 再也不走redis了 ! 大連查詢請求過來,,,,產生了雪崩效應~
這時候使用限流 服務降級、熔斷的方案 這三個方案是針對redis的上一層的
Redis雪崩效應的解決方案
一、可使用分佈式鎖 單機版的話本地鎖
二、消息中間件方式
三、一級和二級緩存 Redis+Ehchache
四、均攤分配Redis的key的失效時間
解釋:
一、 當忽然有大量請求到數據庫服務器時候,進行請求限制。使用所的機制,保證只有一個線程(請求)操做。不然進行排隊等待(集羣分佈式鎖,單機本地鎖)。減小服務器吞吐量,效率低。
加入鎖!
保證只能有一個線程進入 實際上只能有一個請求在執行查詢操做
也能夠在此處進行使用限流的策略~
二、使用消息中間件解決
這種方案是最靠譜的方案!
消息中間件 能夠解決高併發!!!
若是大量的請求進行訪問時候,Redis沒有值的狀況,會將查詢的結果存放在消息中間件中(利用了MQ同步特性)
查不到時候 走MQ
三、一級二級緩存
四、均攤分配redis key的失效時間
不讓在同一時間失效,不一樣key失效時間不一樣