一、什么是緩存雪崩
緩存雪崩就是指緩存由於某些原因(比如 宕機、cache服務掛了或者不響應)整體crash掉了,導致大量請求到達后端數據庫,從而導致數據庫崩潰,整個系統崩潰,發生災難。
下面的就是一個雪崩的簡單過程:
1、redis集群徹底崩潰
2、緩存服務大量對redis的請求hang住,占用資源
3、緩存服務大量的請求打到源頭服務去查詢mysql,直接打死mysql
4、源頭服務因為mysql被打死也崩潰,對源服務的請求也hang住,占用資源
5、緩存服務大量的資源全部耗費在訪問redis和源服務無果,最后自己被拖死,無法提供服務
6、nginx無法訪問緩存服務,redis和源服務,只能基於本地緩存提供服務,但是緩存過期后,沒有數據提供
7、網站崩潰
雪崩問題在國外叫做:stampeding herd(奔逃的野牛),指的的cache crash后,流量會像奔逃的野牛一樣,打向后端。

導致這種現象可能的原因:
1、例如 “緩存並發”,“緩存穿透”,“緩存顛簸” 等問題,這些問題也可能會被惡意攻擊者所利用。
2、例如 某個時間點內,系統預加載的緩存周期性集中失效了。解決方法:可以通過設置不同的過期時間,來錯開緩存過期,從而避免緩存集中失效。
二、預防和解決緩存雪崩問題
1)事前解決方案
- 保證緩存層服務高可用性
和飛機都有多個引擎一樣,如果緩存層設計成高可用的,即使個別節點、個別機器、甚至是機房宕掉,依然可以提供服務,例如 Redis Sentinel 和 Redis Cluster 都實現了高可用。
部署方式一:雙機房部署,一套Redis Cluster,部分機器在一個機房,另一部分機器在另外一個機房。
部署方式二:雙機房部署,兩套Redis Cluster,兩套Redis Cluster之間做一個數據同步。
2)事中解決方案:
- 對緩存訪問進行 資源隔離(熔斷)、Fail Silent 降級
避免所有資源hang在訪問緩存上,當判斷緩存出現問題,則自動進行熔斷並按預設進行降級操作。
- ehcache本地緩存
應對零散的緩存中數據被清除掉的現象,另外一個主要預防緩存徹底崩潰,ehcache的緩存還能支撐一陣。
- 對源服務訪問進行 限流、資源隔離(熔斷)、Stubbed 降級。
無論是緩存層還是存儲層都會有出錯的概率,可以將它們視同為資源。作為並發量較大的系統,假如有一個資源不可用,可能會造成線程全部 hang 在這個資源上,造成整個系統不可用。
相信大家一定遇到過這樣的頁面:這些應該就是淘寶的降級策略。

降級在高並發系統中是非常正常的:比如推薦服務中,如果個性化推薦服務不可用,可以降級補充熱點數據,不至於造成前端頁面是開天窗。
在實際項目中,我們需要對重要的資源 ( 例如 Redis、 MySQL、 Hbase、外部接口 ) 都進行隔離,讓每種資源都單獨運行在自己的線程池中,即使個別資源出現了問題,對其他服務沒有影響。但是線程池如何管理,比如如何關閉資源池,開啟資源池,資源池閥值管理,這些做起來還是相當復雜的,這里推薦一個 Java 依賴隔離工具 Hystrix(https://github.com/Netflix/Hystrix)。
3)事后解決方案
- Redis數據備份和恢復
- 快速緩存預熱
4)提前演練
在項目上線前,演練緩存層宕掉后,應用以及后端的負載情況以及可能出現的問題,在此基礎上做一些預案設定。