Redis Sentinel是一個分佈式架構,其中包含若干個 Sentinel
節點和 Redis
數據節點,每一個 Sentinel
節點會對數據節點和其他 Sentinel
節點進行監控,當它發現節點不可達時,會對節點作下線標識。若是被標識的是主節點,它還會和其餘 Sentinel
節點進行「協商」,當大多數 Sentinel
節點都認爲主節點不可達時,它們會選舉出一個 Sentinel
節點來完成自動故障轉移的工做(這個選舉機制一會介紹),同時會將這個變化實時通知給 Redis
應用方。整個過程徹底是自動的
,不須要人工來介入,因此這套方案頗有效地解決了 Redis
的高可用
問題,能夠理解爲:以前的主從複製中增長了幾個哨兵(這裏注意是幾個而不是一個)來監控redis
,若是主機掛了,哨兵會通過選舉在從機中選出一個redis
做爲主機,這樣就沒必要手動切換了。php
1·
監控:Sentinel 節點會按期檢測 Redis 數據節點、其他 Sentinel 節點是否可達。2·
通知:Sentinel 節點會將故障轉移的結果通知給應用方。3·
主節點故障轉移:實現從節點晉升爲主節點並維護後續正確的主從關係。4·
配置提供者:在 Redis Sentinel
結構中,客戶端在初始化的時候鏈接的是 Sentinel
節點集合,從中獲取主節點信息。
同時Redis Sentinel
包含了若個 Sentinel
節點,這樣作也帶來了兩個好處:5·
對於節點的故障判斷是由多個 Sentinel
節點共同完成,這樣能夠有效地防止誤判。6·
Sentinel 節點集合是由若干個 Sentinel
節點組成的,這樣即便個別 Sentinel
節點不可用,整個 Sentinel
節點集合依然是健壯的。
Sentinel 節點自己就是獨立的 Redis
節點,只不過它們有一些特殊,它們不存儲數據,只支持部分命令node
1.主節點出現故障,此時兩個從節點與主節點失去鏈接,主從複製失敗。
2.每一個Sentinel
節點經過按期監控發現主節點出現了故障。
3.多個 Sentinel
節點對主節點的故障達成一致會選舉出其中一個節點做爲領導者負責故障轉移。
4.Sentinel
領導者節點執行了故障轉移,整個過程基本是跟咱們手動調整一致的slaveof no one
,只不過是自動化完成的。
5.故障轉移後整個 Redis Sentinel
的結構,從新選舉了新的主節點,而且會通知給客戶端。redis
sentinel monitor <master-name> <ip> <port> <count>
監控的主節點的名字
、IP
和端口
,最後一個count
的意思是有幾臺 Sentinel 發現有問題,就會發生故障轉移,例如 配置爲2,表明至少有2個 Sentinel 節點認爲主節點不可達,那麼這個不可達的斷定纔是客觀的。對於設置的越小,那麼達到下線的條件越寬鬆,反之越嚴格。通常建議將其設置爲 Sentinel 節點的一半加1
注意:最後的參數不得大於conut(sentinel)緩存
sentinel down-after-millseconds <master-name> 30000
這個是超時的時間(單位爲毫秒)。打個比方,當你去 ping 一個機器的時候,多長時間後仍 ping 不通,那麼就認爲它是有問題
3.sentinel parallel-syncs <master-name> 1
當 Sentinel 節點集合對主節點故障斷定達成一致時,Sentinel 領導者節點會作故障轉移操做,選出新的主節點,原來的從節點會向新的主節點發起復制操做,parallel-syncs
就是用來限制在一次故障轉移以後,每次向新的主節點發起復制操做的從節點個數,指出 Sentinel 屬於併發
仍是串行
。1表明每次只能複製一個,能夠減輕 Master 的壓力;swoole
4.sentinel auth-pass <master-name> <password>
網絡
若是 Sentinel
監控的主節點配置了密碼,sentinel auth-pass
配置經過添加主節點的密碼,防止 Sentinel
節點對主節點沒法監控。
5.sentinel failover-timeout mymaster 180000
表示故障轉移的時間。
6.sentinel支持的合法命令以下:SENTINEL masters
顯示被監控的全部master
以及它們的狀態.SENTINEL master <master name>
顯示指定master
的信息和狀態;SENTINEL slaves <master name>
顯示指定master
的全部slave
以及它們的狀態;SENTINEL get-master-addr-by-name <master name>
返回指定master的ip和端口,若是正在進行failover
或者failover
已經完成,將會顯示被提高爲master
的slave
的ip
和端口。SENTINEL failover <master name>
強制sentinel
執行failover
,而且不須要獲得其餘sentinel
的贊成。可是failover
後會將最新的配置發送給其餘sentinel
。架構
修改配置sentinel monitor <master-name> <ip> <port> <count>
添加新的監聽併發
SENTINEL REMOVE <master-name>
放棄對某個master監聽異步
SENTINEL set failover-timeout <master-name> 180000
設置配置選項分佈式
`Master`可能會由於某些狀況宕機了,若是在客戶端是固定一個地址去訪問,確定是不合理的,因此客戶端請求是請求哨兵,從哨兵獲取主機地址的信息,或者是從機的信息。能夠實現一個例子
一、隨機選擇一個哨兵鏈接,獲取主機、從機信息
二、模擬客戶端定時訪問,實現簡單輪訓效果,輪訓從節點
三、鏈接失敗重試訪問
這裏我簡單寫個例子,這裏我用了swoole
的定時器
<?php class Round{ static $lastIndex=0; public function select($list){ $currentIndex=self::$lastIndex; //當前的index $value=$list[$currentIndex]; if($currentIndex+1>count($list)-1){ self::$lastIndex=0; }else{ self::$lastIndex++; } return $value; } } $sentinelConf=[ ['ip'=>'xxx','port'=>xxx], ['ip'=>'xxx','port'=>xxx], ['ip'=>'xxx','port'=>xxx] ]; //隨機訪問 $sentinelInfo=$sentinelConf[array_rand($sentinelConf)]; $redis=new Redis(); $redis->connect($sentinelInfo['ip'],$sentinelInfo['port']); //rawCommand參數 1 command 2 arguments 3. $slavesInfo=$redis->rawCommand('SENTINEL','slaves','mymaster'); $slaves=[]; foreach ($slavesInfo as $val){ $slaves[]=['ip'=>$val[3],'port'=>$val[5]]; } //加載到緩存當中,能夠記錄此次訪問的時間跟上次的訪問時間 //模擬客戶端訪問 swoole_timer_tick(600,function () use($slaves) { //輪訓 $slave=(new Round())->select($slaves); try{ $redis=new Redis(); $redis->connect($slave['ip'],$slave['port']); var_dump($slave,$redis->get('username')); }catch (\RedisException $e){ } });
說完了 Sentinel
的代碼實現,不少人對 Sentinel
還不懂其原理。那麼接下來就來看下 Sentinel
的實現原理,主要分爲如下三個步驟。
每10
秒每一個 Sentinel
對 Master
和 Slave
執行一次 Info Replication
。
每2
秒每一個 Sentinel
經過 Master
節點的 channel
交換信息(pub/sub
)。
每1
秒每一個 Sentinel
對其餘 Sentinel
和 Redis
執行 ping
。
第一個定時任務,指的是 Redis Sentinel
能夠對 Redis
節點作失敗判斷和故障轉移,在 Redis
內部有三個定時任務做爲基礎,來 Info Replication
發現 Slave
節點,這個命令能夠肯定主從關係。
第兩個定時任務,相似於發佈訂閱,Sentinel
會對主從關係進行斷定,經過 _sentinel_:hello
頻道交互。瞭解主從關係能夠幫助更好的自動化操做 Redis
。而後 Sentinel
會告知系統消息給其它 Sentinel
節點,最終達到共識,同時 Sentinel
節點可以互相感知到對方。
第三個定時任務,指的是對每一個節點和其它 Sentinel
進行心跳檢測,它是失敗斷定的依據。
當有一臺 Sentinel
機器發現問題時,它就會主觀對它主觀下線,可是當多個 Sentinel
都發現有問題的時候,纔會出現客觀下線。
咱們先來回顧一下 Sentinel
的配置。
sentinel monitor <master-name> <ip> <port> <count> sentinel down-after-milliseconds <master-name> 30000
Sentinel
會 ping
每一個節點,若是超過30
秒,依然沒有回覆的話,作下線的判斷。
每一個 Sentinel
節點對 Redis
節點失敗的「偏見」。之因此是偏見,只是由於某一臺機器30秒內沒有獲得回覆。
這個時候須要全部 Sentinel
節點都發現它30
秒內無回覆,纔會達到共識。
1.每一個作主觀下線的sentinel
節點,會向其餘的sentinel
節點發送命令,要求將它設置成爲領導者
2.收到命令sentinel
節點,若是沒有贊成經過其它節點發送的命令,那麼就會贊成請求,不然就會拒絕
3.若是sentinel
節點發現本身票數超過半數,同時也超過了sentinel monitor <master-name> <ip> <port> <count>
超過count
個的時候,就會成爲領導者
如何選擇「合適的」Slave
節點Redis
內部實際上是有一個優先級配置的,在配置文件中 slave-priority
,這個參數是 Salve 節點的優先級配置,若是存在則返回,若是不存在則繼續。
當上面這個優先級不知足的時候,Redis
還會選擇複製偏移量最大的 Slave
節點,若是存在則返回,若是不存在則繼續。之因此選擇偏移量最大,這是由於偏移量越小,和 Master
的數據越不接近,如今 Master
掛掉了,說明這個偏移量小的機器數據也可能存在問題,這就是爲何要選偏移量最大的 Slave
的緣由。
若是發現偏移量都同樣,這個時候 Redis
會默認選擇 runid
最小的節點。
1.Sentinel
節點不該該部署在一臺物理「機器」上。
這裏特地強調物理機是由於一臺物理機作成了若干虛擬機或者現今比較流行的容器,它們雖然有不一樣的 IP 地址,但實際上它們都是同一臺物理機,同一臺物理機意味着若是這臺機器有什麼硬件故障,全部的虛擬機都會受到影響,爲了實現 Sentinel 節點集合真正的高可用,請勿將 Sentinel
節點部署在同一臺物理機器上。
2.部署至少三個且奇數
個的 Sentinel
節點。
3.個以上是經過增長 Sentinel
節點的個數提升對於故障斷定的準確性,由於領導者選舉須要至少一半加1個節點,奇數個節點能夠在知足該條件的基礎上節省一個節點。
哨兵集羣在發現master node
掛掉後會進行故障轉移,也就是啓動其中一個slave node
爲master node
。在這過程當中,可能會致使數據丟失的狀況。
由於master->slave
的複製是異步,因此可能有部分還沒來得及複製到slave就宕機了,此時這些部分數據就丟失了,這個我至今沒找到解決的辦法,但願有人更正。
腦裂,也就是說,某個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
,數據複製和同步的延遲不能超過10
秒
若是說一旦全部的slave
,數據複製和同步的延遲都超過了10
秒鐘,那麼這個時候,master
就不會再接收任何請求了
上面兩個配置能夠減小異步複製和腦裂致使的數據丟失
在異步複製的過程中,經過min-slaves-max-lag
這個配置,就能夠確保的說,一旦slave
複製數據和ack
延遲時間太長,就認爲可能master
宕機後損失的數據太多了,那麼就拒絕寫請求,這樣就能夠把master
宕機時因爲部分數據未同步到slave致使的數據丟失下降到可控範圍內
集羣腦裂由於client
還沒來得及切換成新的master
,還繼續寫向舊的master的數據可能就丟失了經過min-slaves-to-write
確保必須是有多少個從節點鏈接,而且延遲時間小於min-slaves-max-lag
多少秒。
對於client
來說,就須要作些處理,好比先將數據緩存到內存當中,而後過一段時間處理,或者鏈接失敗,接收到錯誤切換新的master
處理。