redis 擊穿、穿透、雪崩產生原因及解決方案


一、前言

從架構的一個整體性來看,redis產生擊穿、穿透、雪崩的情況的前提條件都是redis做緩存使用,並且產生了高並發,正常情況下我們利用關系型數據庫(mysql、oracle等等)作為數據存儲,如果並發量不大的情況完全可以hold住客戶端的請求,如果高並發產生關系型數據庫I/O就會成為瓶頸,這時會導致請求響應緩慢,嚴重會導致DB直接癱瘓。這時就要想盡一切辦法阻止大量請求直接到達數據庫,所以無論是Nginx限流、網關的限流、server層的降級處理、redis的緩存,唯一目的就是阻止大量請求直接到達DB。下面我們在這些理論的基礎上討論一下redis的擊穿、穿透、雪崩。

二、redis的擊穿

1、前提:redis肯定做緩存使用,並且key過期。【注意】這里是key失效,不是key不存在;

 2、分析:

redis只要做緩存使用一定會受到內存大小的限制,所以我們在使用redis做緩存時,無論是緩存key的過期時間到了還是redis內部的淘汰策略(LRU LFU) 都會有緩存失效的一瞬間,如果偏偏就是那么巧,在key失效的時大量的並發請求到達server ,然而此時緩存不存在,導致大量請求到達DB。這就是產生擊穿的原因。

3、解決方案:

3.1、redis是一個單進程單實例的。所以並發請求都死排着隊進入redis的,所以分為以下幾個步驟:
  • 第一個請求進來發現沒有key,立刻使用setNx(相當於一把鎖);
  • 如果設置成功訪問數據庫,失敗則睡眠一會再訪問;
3.2、當然上面的方法會產生死鎖的可能(如果第一個請求掛了),解決方法:
  • 設置鎖的同時添加過期時間,如果超時自動釋放鎖資源;
  • 這里也存在一個問題那就是過期時間設置大小的問題,設置大了,如果第一個請求掛了,會導致后面的大量請求等待時間過長而超時,如果設置時間過短,自己沒處理完別的請求進來了,這樣循環下去,這也會存在一定的並發請求。
3.3、解決過期時間長短問題:
  • 可以開啟一個守護線程來監控數據有沒有從DB中獲取出來放入緩存,如果沒有完成則給鎖續時間;
  • 可以使用已經封裝好的 Redisson;
  • 同時也看到了redis實現分布式鎖的復雜性,所以這里你也可以使用zookeeper來實現分布式鎖;

三、redis穿透

1、前提:肯定發生了高並發,並且客戶端請求的數據數據庫不存在,更別期望緩存會存在。

 2、分析:

  • 舉個例子你是一個賣家電的電商平台,別人就在你的客戶端惡意並發請求母嬰產品,這時就會導致大量的並發請求到達DB,造成數據庫壓力過大。

3、解決方案:

  • 使用布隆過濾器,這里你可以有幾種集成的方案:1、直接放在客戶端算法+bitmap;2、客戶端只包含布隆算法,把bitmap放在redis中;3、redis集成布隆模塊;

 

  •  當然布隆過濾器存在一個問題,就是只能添加不能刪除,如果你可以容忍這個問題,ok 直接使用沒問題,如果不能容忍,可以使用布谷鳥等其他過濾器來替換;

四、redis 雪崩

1、前提:產生了並發請求,並且有大批量的key同時失效了;

 2、分析:

  • 這里要區分你的業務場景,你的緩存具不具有時點性,如果不具有時點性當然隨機過期時間就可以解決;如果具有時點性,我的redis大批量的key就要在一天內的某個點全部失效,這里只能強依賴於擊穿的解決方案,引入分布式鎖;

3、解決方案:

 五、總結

無論是redis的擊穿、穿透還是雪崩,他們產生的前提都是存在並發請求,並且redis都未攔截到請求,導致大量的請求到達數據庫,從整體的一個角度看我們主要解決的就是阻止大量的並發請求同時到達數據庫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM