Docker部署Redis集羣----第十一節(docker-redis哨兵集羣總結)
本來是計劃開始新篇章redis-cluster集羣的,但是總覺得缺點什麼,所以本篇章對前兩個篇章做一個總結來引流我們接下來的集羣。
哨兵節點常見的問題:
哨兵集羣在發現master node掛掉後會進行故障轉移,也就是啟動其中一個slave node為master node。在這過程中,可能會導致數據丟失的情況。
1、非同步複製導致數據丟失:
因為master->slave的複製是非同步,所以可能有部分還沒來得及複製到slave就宕機了,此時這些部分數據就丟失了。
2、集羣腦裂導致數據丟失 :
腦裂,也就是說,某個master所在機器突然脫離了正常的網路,跟其它slave機器不能連接,但是實際上master還運行著。
照成的結果:
- 此時哨兵可能就會認為master宕機了,然後開始選舉,將其它從節點slave切換成master。這時候集羣裏就會有2個master,也就是所謂的腦裂。
- 此時雖然某個slave被切換成了master,但是可能client還沒來得及切換成新的master,還繼續寫向舊的master的數據可能就丟失了。
- 因此舊master再次恢復的時候,會被作為一個slave掛到新的master上去,自己的數據會被清空,重新獲取新的master複製數據。
所以對以上的解決方案:
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有1個從節點slave和主節點master是連接狀態,數據複製和同步的延遲不能超過10秒時允許寫入;
如果說一旦所有的slave,數據複製和同步的延遲都超過了10秒鐘,那麼這個時候,master就不會再接收任何請求了。
這樣我們可以減少非同步複製和腦裂導致的數據丟失
這個配置的意思是:
1、非同步複製導致的數據丟失:
在非同步複製的過程當中,通過min-slaves-max-lag這個配置,就可以確保的說,一旦slave複製數據和ack延遲時間太長,
就認為可能master宕機後損失的數據太多了,那麼就拒絕寫請求,這樣就可以把master宕機時由於部分數據
未同步到slave導致的數據丟失降低到可控範圍內。
2、集羣腦裂導致的數據丟失:
集羣腦裂因為client還沒來得及切換成新的master,還繼續寫向舊的master的數據可能就丟失了
通過min-slaves-to-write 確保必須是有多少個從節點連接,並且延遲時間小於min-slaves-max-lag
多少秒。
這個配置在第四篇章也有寫到。
客戶端處理方式:
對於client來講,就需要做些處理,比如先將數據緩存到內存當中,然後過一段時間處理,或者連接失敗,接收到錯誤切換新的master處理。
這裡我們可以對第九篇章輪詢代碼進行修改
//邏輯處理執行
$retry=3; //重試三次
try{
$redis=new Redis();
$redis->connect($slave[ip],$slave[port],0.5);
}catch(Exception $e){
var_dump($e->getMessage());
while ($e->getMessage()==Redis server went away && $retry-- ){
sleep(1);
var_dump($retry,重新嘗試連接);
}
//訪問哨兵獲取新的主節點節點
//while ($retry-- ){
// var_dump($retry,重新嘗試連接);
//}
//$masterInfo=$redis->rawCommand(SENTINEL,get-master-addr-by-name,mymaster); //從節點信息
}
這樣做的目的能使客戶端擁有更好的體驗度。
redis+哨兵的主從問題:
假設我們在一臺主從機器上配置了300G內存,但是業務需求是需要500G的時候,主從結構+哨兵可以實現高可用故障切換+冗餘備份,但是並不能解決數據容量的問題,用哨兵redis每個實例也是全量存儲,每個redis存儲的內容都是完整的數據,浪費內存且有木桶效應。為了最大化利用內存,可以採用cluster羣集,就是分散式存儲。即每臺redis存儲不同的內容。
Redis 分散式方案一般有兩種:
1、客戶端分區方案,優點是分區邏輯可控,缺點是需要自己處理數據路由、高可用、故障轉移等問題,比如在redis2.8之前通常的做法是獲取某個key的hashcode,然後取餘分佈到不同節點,不過這種做法無法很好的支持動態伸縮性需求,一旦節點的增或者刪操作,都會導致key無法在redis中命中。