相對來說,考慮的比較完善的一套方案,分為事前,事中,事后三個層次去思考怎么來應對緩存雪崩的場景
1、事前解決方案
發生緩存雪崩之前,事情之前,怎么去避免redis徹底掛掉
redis本身的高可用性,復制,主從架構,操作主節點,讀寫,數據同步到從節點,一旦主節點掛掉,從節點跟上
雙機房部署,一套redis cluster,部分機器在一個機房,另一部分機器在另外一個機房
還有一種部署方式,兩套redis cluster,兩套redis cluster之間做一個數據的同步,redis集群是可以搭建成樹狀的結構的
一旦說單個機房出了故障,至少說另外一個機房還能有些redis實例提供服務
2、事中解決方案
redis cluster已經徹底崩潰了,已經開始大量的訪問無法訪問到redis了
(1)ehcache本地緩存
所做的多級緩存架構的作用上了,ehcache的緩存,應對零散的redis中數據被清除掉的現象,另外一個主要是預防redis徹底崩潰
多台機器上部署的緩存服務實例的內存中,還有一套ehcache的緩存
ehcache的緩存還能支撐一陣
(2)對redis訪問的資源隔離
(3)對源服務訪問的限流以及資源隔離
3、事后解決方案
(1)redis數據可以恢復,做了備份,redis數據備份和恢復,redis重新啟動起來
(2)redis數據徹底丟失了,或者數據過舊,快速緩存預熱,redis重新啟動起來
redis對外提供服務
緩存服務里,熔斷策略,自動可以恢復,half-open,發現redis可以訪問了,自動恢復了,自動就繼續去訪問redis了
基於hystrix的高可用服務這塊技術之后,先講解緩存服務如何設計成高可用的架構
緩存架構應對高並發下的緩存雪崩的解決方案,基於hystrix去做緩存服務的保護
redis集群崩潰的時候,會怎么樣?
(1)首先大量的等待,超時,報錯
(2)如果是短時間內報錯,會直接走fallback降級,直接返回null
(3)超時控制,你應該判斷說redis訪問超過了多長時間,就直接給timeout掉了
不推薦說用默認的值,一般不太精准,redis的訪問你首先自己先統計一下訪問時長的百分比,hystrix dashboard,TP90 TP95 TP99
一般來說,redis訪問,假設說TP99在100ms,那么此時,你的timeout稍微多給一些,100ms。
1、timeout超時控制
HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(int value)
意義在於哪里,一旦說redis出現了大面積的故障,此時肯定是訪問的時候大量的超過100ms,大量的在等待和超時
就可以確保說,大量的請求不會卡住過長的時間,比如說卡住個1s,500ms,100ms直接就報timeout,走fallback降級了
2、熔斷策略
(1)circuitBreaker.requestVolumeThreshold
設置一個rolling window,滑動窗口中,最少要有多少個請求時,才觸發開啟短路
舉例來說,如果設置為20(默認值),那么在一個10秒的滑動窗口內,如果只有19個請求,即使這19個請求都是異常的,也是不會觸發開啟短路器的
HystrixCommandProperties.Setter()
.withCircuitBreakerRequestVolumeThreshold(int value)
我們應該根據我們自己的平時的訪問流量去設置,而不是用默認值,比如說,我們認為平時一般的時候,流量也可以在每秒在QPS 100,10秒的滑動窗口就是1000
一般來說,你可以設置這樣的一個值,根據你自己的系統的流量去設置
假如說,你設置的太少了,或者太多了,都不太合適
舉個例子,你設置一個20,結果在晚上最低峰的時候,剛好是30,可能晚上的時候因為訪問不頻繁,大量的找不到緩存,可能超時頻繁了一些,結果直接就給短路了
(2)circuitBreaker.errorThresholdPercentage
設置異常請求量的百分比,當異常請求達到這個百分比時,就觸發打開短路器,默認是50,也就是50%
HystrixCommandProperties.Setter()
.withCircuitBreakerErrorThresholdPercentage(int value)
(3)circuitBreaker.sleepWindowInMilliseconds
設置在短路之后,需要在多長時間內直接reject請求,然后在這段時間之后,再重新導holf-open狀態,嘗試允許請求通過以及自動恢復,默認值是5000毫秒
HystrixCommandProperties.Setter()
.withCircuitBreakerSleepWindowInMilliseconds(int value)
限流過后,就會導致什么呢,比如redis集群崩潰了,雪崩,大量的請求涌入到商品服務調用的command中,是線程池不夠
reject,被reject掉的請求就會去執行fallback降級邏輯
那么nginx本地緩存肯定就沒了,redis已經崩潰了,ehcache中找不到這條數據對應的緩存
只能從源頭的商品服務里面去查詢,但是被限流了,這個請求只能走降級方案
stubbed fallback降級機制,殘缺的降級
一般這種情況下,就是說,用請求參數中少量的數據,加上純內存中緩存的少量的數據來提供殘缺的數據服務
冷數據,也就是說你可以這么認為,將一些過時的數據,比如一個商品信息一周前的版本,放入大數據的在線存儲中,比如比較合適做冷數據存放的是hbase
hadoop,離線批處理,hdfs分布式存儲,yarn分布式資源調度(跟hbase沒關系),mapreduce分布式計算
hbase,基於hdfs分布式存儲基礎之上,封裝了一個系統,叫做hbase,分布式在線存儲,分布式NoSQL數據庫,里面可以放大量的冷數據
hbase,可以做商品服務熱數據是放mysql,可以將一周前,一個月前的數據快照,做一份冷備放到hbase來備用
發送請求去訪問hbase,去加載冷數據,hbase本身是分布式的,所以也是可以承載高並發的訪問的(分布式的特性比mysql),即使這個時候大量並發到了hbase,
多級降級機制,先走hbase冷備,然后再走stubbed fallback
緩存雪崩的回顧
1、事前,redis高可用性,redis cluster,sentinal,復制,主從,從->主,雙機房部署
2、事中,ehcache可以抗一抗,redis掛掉之后的資源隔離、超時控制、熔斷,商品服務的訪問限流、多級降級,緩存服務在雪崩場景下存活下來,基於ehcache和存活的商品服務提供數據
3、事后,快速恢復Redis,備份+恢復,快速的緩存預熱的方案