1. 程式人生 > 其它 >13、哨兵模式

13、哨兵模式

1、sentinel哨兵模式介紹
  • sentinel(哨兵)是用於監控redis叢集中master狀態的工具,是redis的高可用性解決方案。sentinel系統可以監視一個或者多個master服務,以及這些master服務的所有從服務;當某個master服務下線時,自動將該master下的某個從伺服器升級為master服務替代已下線的master服務繼續處理請求。
  • sentinel可以讓redis實現主從複製,當一個叢集中的master失效之後,sentinel可以選舉出一個新的master用於自動接替master的工作,叢集中的其他redis伺服器自動指向新的master同步資料一般建議sentinel採取奇數臺,防止某一臺sentinel無法連線到master導致誤切換
    。其結構如下:
  • redis-sentinel是redis官方推薦的高可用性(HA)解決方案,當用redis做master-slave的高可用方案時,假如master宕機了,redis本身(包括它的很多客戶端)都沒有實現自動進行主備切換,而redis-sentinel本身也是一個獨立執行的程序,它能監控多個master-slave叢集,發現master宕機後能進行自動切換sentinel由一個或多個sentinel例項組成的sentinel系統,可以監視任意多個主伺服器,以及這些主伺服器屬下的所有從伺服器,並在被監視的主伺服器進入下線狀態時,自動將下線主伺服器屬下的某個從伺服器升級為新的主伺服器。
  • 如下圖所示:
  • 在server1掉線後:
  • 升級server2為新的主伺服器:
2、sentinel狀態持久化:
    • sentinel的狀態會被持久化地寫入sentinel的配置檔案中。每次當收到一個新的配置時,或者新建立一個配置時,配置會被持久化到硬碟中,並帶上配置的版本戳。這意味著,可以安全的停止和重啟sentinel程序
3、sentinel的作用
  • 監控
    • 不斷的檢查master和slave是否正常執行
    • master存活檢測、master與slave執行情況檢測
  • 通知(提醒)
    • 當被監控的伺服器出現問題時,向其他(哨兵間、客戶端)傳送通知
  • 自動故障轉移
    • 斷開master與slave連線,選取一個slave作為master,將其他slave連線到新的master,並告知客戶端新的伺服器地址
4、sentinel的分散式特性
  • 很顯然,只使用單個sentinel程序來監控redis叢集是不可靠的,當sentinel程序宕掉後(sentinel本身也有單點問題,single-point-of-failure)整個集群系統將無法按照預期的方式執行。所以有必要將sentinel叢集,這樣有幾個好處:
    • 即使有一些sentinel程序宕掉了,依然可以進行redis叢集的主備切換
    • 如果只有一個sentinel程序,如果這個程序執行出錯或者是網路堵塞,那麼將無法實現redis叢集的主備切換(單點問題)
    • 如果多個sentinel,redis的客戶端可以隨意地連線任意一個sentinel來獲得關於redis叢集的資訊
5、注意
  • 哨兵也是一臺redis伺服器,只是不提供資料服務
  • 通常哨兵配置數量為單數
6、配置哨兵
  • 配置一拖二的主從結構
  • 配置三個哨兵(配置相同,埠不同)
    • sentinel auth-pass <伺服器名稱> <password>
      • sentinel auth-pass mymaster itcast
      • 連線伺服器口令
    • sentinel down-after-milliseconds <自定義服務名稱><主機地址><埠><主從伺服器總量>
      • sentinel monitor mymaster 192.168.194.131 6381 1
      • 設定哨兵監聽的主伺服器資訊,最後的引數決定了最終參與選舉的伺服器數量(-1)
    • sentinel down-after-milliseconds <服務名稱><毫秒數(整數)>
      • sentinel down-after-milliseconds mymaster 3000
      • 指定哨兵在監控Redis服務時,判定伺服器掛掉的時間週期,預設30秒(30000),也是主從切換的啟動條件之一
    • sentinel parallel-syncs <服務名稱><伺服器數(整數)>
      • sentinel parallel-syncs mymaster 1
      • 指定同時進行主從的slave數量,數值越大,要求網路資源越高,要求約小,同步時間約長
    • sentinel failover-timeout <服務名稱><毫秒數(整數)>
      • sentinel failover-timeout mymaster 9000
      • 指定出現故障後,故障切換的最大超時時間,超過該值,認定切換失敗,預設3分鐘
    • sentinel notification-script <服務名稱><指令碼路徑>
      • 伺服器無法正常聯通時,設定的執行指令碼,通常除錯使用
  • 啟動哨兵
redis-sentinel sentinel- 埠號 .conf
7、哨兵工作原理
  • 階段1:監控階段
    • 監控步驟:(先啟動主從伺服器再啟動哨兵)
      • 啟動哨兵,連線上master之後傳送info指令,獲取master的資訊
      • 哨兵和master之間建立cmd連線方便傳送指令,同時在哨兵端儲存了所有資訊包括master/slaves/sentinels,在master端也儲存了所有資訊包括master/slaves/sentinels
      • 哨兵根據獲得的slave資訊去連線每一個slave,傳送info指令獲取slave詳細資訊
      • 啟動第二個哨兵也會自動去連線master,傳送info指令,會發現master已經和其他哨兵連線過同時建立cmd連線,此時哨兵端儲存資訊包括master/slave/sentinels(包括之前連線的哨兵),兩個哨兵之間也會建立連線
      • 當第三個哨兵啟動的時候,也會進行之前的操作

  • 階段二:通知階段
  • 階段三:故障轉移階段
    • 故障轉移流程
      • 其中一個sentinel向master傳送資訊,一段時間內master沒有迴應,標記狀態SRI_S_DOWN(主觀下線)
      • sentinel在自己內網中告訴其他哨兵,master掛了。其他哨兵也去連線master,半數以上的哨兵發現master掛了,那就是真的掛了,狀態改成SRI_O_DOWN(客觀下線)
      • 所有的哨兵推選出一個哨兵領導,哨兵根據自己的原則從所有的slave中推選出新的master,其他的slave切換新的master,故障恢復後原master作為slave

  • 哨兵推選新的master的原則
    • 哨兵挑選出新的master原則
      • 線上的
      • 響應慢的
      • 與原master斷開時間久的
      • 優先原則:
        • 優先順序
        • offset
        • runid
    • 傳送指令(sentinel)
      • 向新的master傳送slaveof no one
      • 向其他slave傳送slaveof新的masterIP埠
8、sentinel工作方式(每個sentinel例項都執行的定時任務)
  • 每個sentinel以每秒鐘一次的頻率向它所知的master,slave以及其他sentinel例項傳送一個ping命令
    • 如果一個例項(instance)距離最後一次有效回覆ping命令的時間超過own-after-milliseconds選項所指定的值,則這個例項會被sentinel標記為主觀下線(sdown)
    • 如果一個master被標記為主管下線(sdown),則正在監視這個master的所有sentinel要以每秒一次的頻率確認master的確進入了主觀下線狀態
    • 當有足夠數量的sentinel(2/n+1個)在指定的時間範圍內確認master的確進入了主觀下線狀態,則master會被標記為客觀下線(odiwn)
  • 在一般情況下,每個sentinel會以每10s一次的頻率向它已知的所有master、slave傳送info命令
    • 當master被sentinel標記為客觀下線時,sentinel向下線的master的所有slave傳送info命令的頻率會從10s一次改為每秒1次
    • 若沒有足夠數量的sentinel同意master已經下線,master的客觀下線狀態就會被移除。若master重新向sentinel的ping命令返回有效回覆,master的主觀下線狀態就會被移除
9、三個定時任務(sentinel在內部有3個定時任務)
  • 每10s每個sentinel會對master和slave執行info命令,這個任務達到兩個目的:
    • 發現slave節點
    • 確認主從關係
  • 每2s每個sentinel通過master節點的channel交換資訊(pub/sub)。master節點有一個釋出訂閱的頻道(__sentinel__:hello)。sentinel節點通過__sentinel__:hello頻道進行資訊交換(對節點的"看法"和自身的資訊)。達成共識。
  • 每1s每個sentinel對其他sentinel和redis節點進行ping操作(相互監控),這個其實就是一個心跳檢測,是失敗判定的依據。
10、什麼是主觀下線?
  • 所謂主觀下線(Subjectively Down,簡稱SDOWN)指的是單個sentinel例項對伺服器做出的下線判斷,即單個sentinel認為某個服務下線(有可能是接收不到訂閱,之間的網路不通等等原因)
  • 主觀下線就是說如果伺服器在down-after-milliseconds給定的毫秒數之內,沒有返回sentinel傳送的ping命令的回覆,或者返回一個錯誤,那麼sentinel將這個伺服器標記為主觀下線(sdown)
  • sentinel會以每秒一次的頻率向所有與其建立了命令連線的例項(naster、slave、其他sentinel)傳送ping命令,通過判斷ping回覆是有效回覆還是無效回覆來判斷例項是否線上
  • sentinel配置檔案中的down-after-milliseconds設定了判斷主觀下線的時間長度,如果例項在down-after-milliseconds毫秒內,返回的都是無效回覆,那麼Sentinel會認為該例項已(主觀)下線,修改其flags狀態為SRI_S_DOWN。如果多個sentinel監視一個服務,有可能存在多個down-after-milliseconds配置不同,這個在實際生產中要注意。
11、什麼是客觀下線?
  • 客觀下線(Objectively DOWN,簡稱ODOWN)指的是多個sentinel例項在對同一個伺服器做出SDOWN判斷,並且通過sentinel is-master-down-by-addr命令互相交流以後,得出的伺服器下線判斷,然後開啟failover
  • 客觀下線就是說只有在足夠數量(2/n+1)的sentinel都將一個伺服器標記為主觀下線以後,伺服器才會被標記為客觀下線(ODOWN)
  • 只有當master被認為客觀下線時,才會發生故障遷移。
  • 當sentinel監視的某個服務主觀下線後,sentinel會詢問其他監視該服務的sentinel,看它們是否也認為該服務主觀下線,接收到足夠數量(這個值可以配置)的sentinel判斷為主觀下線,即認為該服務客觀下線,並對其做故障轉移操作。
  • sentinel通過傳送sentinel is-master-down-by-addr ip port current_epoch runid 來詢問其他sentinel是否同意服務下線
    • ip:主觀下線的服務ip
    • port:主觀下線的服務埠
    • runid:為*表示檢測客觀下線,為sentinel的runid則用於選舉領頭的sentinel
  • 一個sentinel接收到另一個sentinel發來的is-master-down-by-addr後,提取引數,根據ip和埠,檢測該服務是否主觀下線,並且回覆is-master-down-by-addr,回覆包含三個引數:
    • down_state:
      • 1:已下線
      • 0:未下線
    • leader_runid:領頭sentinel id
    • leader_epoch:領頭sentinel紀元
  • sentinel接收到回覆後,根據配置設定的下線最小數量,達到這個值,即認為該服務客觀下線。
  • 客觀下線條件只適用於主伺服器(master)對於任何其他型別的redis例項,sentinel再將它們判斷為下線前不需要進行協商,所以從伺服器(slave)或者其他sentinel永遠不會達到客觀下線條件。只要一個sentinel發現某個master伺服器進入了客觀下線狀態,這個sentinel就可能被其他sentinel推選出,並對失效的master伺服器執行自動故障遷移操作。
  • 在redis-sentinel的conf檔案裡有這麼兩個配置:
    • sentinel monitor <masterName> <ip> <port> <quorum>
      • masterName:是多某個master+slave組合的一個區分標識(一套sentinel可以監聽多套master+slave這樣的組合的)
      • ip和port:master節點的ip和埠號
      • quorum:這個引數是進行客觀下線的一個依據,意思是至少有quorum個sentinel主觀的認為這個master有故障,才會對這個master進行下線以及故障轉移操作。因為有的時候,某個sentinel節點可能因為自身網路原因,導致無法連線master,而此時master並沒有出現故障,所以這就需要多個sentinel都一致認為該master有問題,才可以進行下一步操作,這就保證了公平性和高可用。
    • sentinel down-after-milliseconds <masterName> <timeout>
      • 這個配置其實就是進行主觀下線的一個依據,timeout是一個毫秒值,表示如果這臺sentinel超過timeout這個時間都無法連通master包括slave(slave不需要客觀下線,因此不需要故障轉移)的話,就會主觀的認為該master已經下線(實際下線需要客觀下線的判斷通過才會下線)
  • 那麼,多個sentinel之間是如何達到共識的呢?
    • 這就是依賴於前面所說的第二個定時任務,某個sentinel先將master節點進行一個主觀下線,然後會將這個判斷通過sentinel is-master-down-by-addr這個命令問對應的節點是否也同樣認為該addr的master節點做客觀下線最後當達成這一共識的sentinel個數達到前面說的quorum設定的這個值時,就會對該master節點下線進行故障轉移quorum這個值一般設定為sentinel個數的二分之一+1。
12、配置版本號
  •  為什麼要先獲得大多數sentinel的認可時才能真正去執行failover(故障轉移)呢?
    • 當一個sentinel被授權後,它將會獲得宕掉的master的一份最新配置版本號,當failover執行結束以後,這個版本號將會被用於最新的配置。因為大多數sentinel都已經知道該版本號已經被要執行failover的sentinel拿走了,所以其他的sentinel都不能再去使用這個版本號。這意味著,每次failover都會附帶有一個獨一無二的版本號。
    • sentinel叢集都遵守一個規則:如果sentinel A推薦sentinel B去執行failover,B會等待一段時間後,自行再次去對同一個master執行failover,這個等待的時間是通過failover-timeout配置項去配置的。從這個規則可以看出,sentinel叢集中的sentinel不會在同一時刻併發去failover同一個master,第一個進行failover的sentinel如果失敗了,另外一個將會在一定時間內進行重新進行failover,以此類推。
    • redis sentinel保證了活躍性:如果大多數sentinel能夠互相通訊,最終將會有一個被授權去進行failover
    • redis centinel也保證了安全性:每個檢視去failover同一個master的sentinel都會得到一個獨一無二的版本號
13、配置傳播
  • 一旦一個sentinel成功地對一個master進行了failover,它將會把關於master的最新配置通過廣播形式通知其他sentinel,其他的sentinel則更新對應master的配置
  • 一個failover要想被成功實行,sentinel必須能夠向選為master的slave傳送 slaveof no one將使得這個從屬伺服器關閉複製功能,並從從屬伺服器轉變回主伺服器,原來同步所得的資料集不會被丟棄)命令,然後能夠通過info命令檢視新master的配置資訊
  • 當將一個slave選舉為master併發送slaveof no one後,即使其他的slave還沒針對新master重新配置自己,failover也被任務是成功了的。然後所有sentinels將會發布新的配置資訊。
  • 新的配置資訊在叢集中互相傳播的方式,就是為什麼我們需要當一個sentinel進行failover時必須被授權一個版本號的原因。
  • 每個sentinel使用"釋出/訂閱"的方式持續地傳播master的配置版本資訊,配置傳播的"釋出/訂閱"的管道是__sentinel__:hello
  • 因為每個配置都有一個版本號,所以以版本號最大的那個為標準。
  • 舉個例子:
    • 假設有一個名為mymaster的地址為192.168.10.202:6379。一開始,叢集中所有的sentinel都知道這個地址,於是為mymaster的配置打上版本號1,。一段時間後mymaster死了,有一個sentinel被授權用版本號2對其進行failover。如果failover成功了,假設地址改為了192.168.10.202:9000,此時配置的版本號為2,進行failover的sentinel會將新配置廣播給其他的sentinel,由於其他sentinel維護的版本號為1,發現新配置的版本號為2時,版本號變大了,說明配置更新了,於是就會採用最新的版本號為2的配置。這意味著sentinel叢集保證了第二種活躍性一個能夠互相通訊的sentinel叢集最終會採用版本號最高且相同的配置
14、sentinel的"仲裁會"
  • 前面我們談到,當一個master被sentinel叢集監控時,需要為它指定一個引數,這個引數指定了當需要判決master為不可用,並且進行failover時,所需要的sentinel數量,可以稱這個引數為票數。
  • 不過,當failover主備切換真正被觸發後,failover並不會馬上進行,還需要sentinel中的大多數sentinel授權後才可以進行failover
  • 當ODOWN時,failover被觸發。failover一旦被觸發,嘗試去進行failover的sentinel會去獲得“大多數”sentinel的授權(如果票數比大多數還要大的時候,則詢問更多的sentinel)這個區別看起來很微妙,但是很容易理解和使用。例如,叢集中有5個sentinel,票數被設定為2,當2個sentinel認為一個master已經不可用了以後,將會觸發failover,但是,進行failover的那個sentinel必須先獲得至少3個sentinel的授權才可以實行failover。如果票數被設定為5,要達到ODOWN狀態,必須所有5個sentinel都主觀認為master為不可用,要進行failover,那麼得獲得所有5個sentinel的授權。
15、選舉領頭sentinel(即領導者選舉)
  • 一個redis服務被判斷為客觀下線時,多個監視該服務的sentinel協商,選舉一個領頭sentinel,對該redis服務進行故障轉移操作。選舉領頭sentinel遵循以下規則:
    • 所有的sentinel都有公平被選舉成領頭的資格。
    • 所有的sentinel都有且只有一次將某個sentinel選舉成領頭的機會(在一輪選舉中),一旦選舉某個sentinel為領頭,不能更改。
    • sentinel設定領頭sentinel是先到先得,一旦當前sentinel設定了領頭sentinel,以後要求設定sentinel為領頭請求都會被拒絕。
    • 每個發現服務客觀下線的sentinel,都會要求其他sentinel將自己設定成領頭。
    • 當一個sentinel(源sentinel)向另一個sentinel(目sentinel)傳送is-master-down-by-addr ip port current_epoch runid命令的時候,runid引數不是*,而是sentinel執行id,就表示源sentinel要求目標sentinel選舉其為領頭。
    • 源sentinel會檢查目標sentinel對其要求設定成領頭的回覆,如果回覆的leader_runid和leader_epoch為源sentinel,表示目標sentinel同意將源sentinel設定成領頭。
    • 如果某個sentinel被半數以上的sentinel設定成領頭,那麼該sentinel既為領頭。
    • 如果在限定時間內,沒有選舉出領頭sentinel,暫定一段時間,再選舉
  • 為什麼要選領導者?
    • 簡單來說,就是因為只能有一個sentinel節點去完成故障轉移
    • sentinel is-master-down-by-addr這個命令有兩個作用,一是確認下線判定,二是進行領導者選舉。
    • 選舉過程:
      • 1)每個做主觀下線的sentinel節點向其他sentinel節點發送上面那條命令,要求將它設定為領導者。
      • 2)收到命令的sentinel節點如果還沒有同意過其他的sentinel傳送的命令(還未投過票),那麼就會同意,否則拒絕。
      • 3)如果該sentinel節點發現自己的票數已經過半且達到了quorum的值,就會成為領導者
      • 4)如果這個過程出現多個sentinel成為領導者,則會等待一段時間重新選舉。
16、Sentinel支援叢集(可以部署在多臺機器上,也可以在一臺物理機上通過多埠實現偽叢集部署)
  • 很顯然,只使用單個sentinel程序來監控redis叢集是不可靠的,當sentinel程序宕掉後(sentinel本身也有單點問題,single-point-of-failure)整個集群系統將無法按照預期的方式執行。所以有必要將sentinel叢集,這樣有幾個好處:
    • 1)即使有一些sentinel程序宕掉了,依然可以進行redis叢集的主備切換;
    • 2)如果只有一個sentinel程序,如果這個程序執行出錯,或者是網路堵塞,那麼將無法實現redis叢集的主備切換(單點問題);
    • 3)如果有多個sentinel,redis的客戶端可以隨意地連線任意一個sentinel來獲得關於redis叢集中的資訊。
17、sentinel叢集注意事項
  • 只有Sentinel 叢集中大多數伺服器認定master主觀下線時master才會被認定為客觀下線,才可以進行故障遷移,也就是說,即使不管我們在sentinel monitor中設定的quorum數是多少,就算是滿足了該值,只要達不到大多數,就不會發生故障遷移
  • 官方建議sentinel至少部署三臺,且分佈在不同機器。這裡主要考慮到sentinel的可用性,假如我們只部署了兩臺sentinel,且quorum設定為1,也可以實現自動故障遷移,但假如其中一臺sentinel掛了,就永遠不會觸發自動故障遷移,因為永遠達不到大多數sentinel認定master主觀下線了。
  • sentinel monitor配置中的master IP儘量不要寫127.0.0.1或localhost,因為客戶端,如jedis獲取master是根據這個獲取的,若這樣配置,jedis獲取的ip則是127.0.0.1,這樣就可能導致程式連線不上master
  • 當sentinel 啟動後會自動的修改sentinel.conf檔案,如已發現的master的slave資訊,和叢集中其它sentinel 的資訊等,這樣即使重啟sentinel也能保持原來的狀態。注意,當叢集伺服器調整時,如更換sentinel的機器,或者新配置一個sentinel,請不要直接複製原來執行過得sentinel配置檔案,因為其裡面自動生成了以上說的那些資訊,我們應該複製一個新的配置檔案或者把自動生成的資訊給刪掉。
  • 當發生故障遷移的時候,master的變更記錄與slave更換master的修改會自動同步到redis的配置檔案,這樣即使重啟redis也能保持變更後的狀態
18、Sentinel之間和Slaves之間的自動發現機制
  • 雖然sentinel叢集中各個sentinel都互相連線彼此來檢查對方的可用性以及互相傳送訊息,但是你不用在任何一個sentinel配置任何其它的sentinel的節點。因為sentinel利用了master的釋出/訂閱機制去自動發現其它也監控了統一master的sentinel節點
    • 通過向名為__sentinel__:hello的管道中傳送訊息來實現
  • 同樣,你也不需要在sentinel中配置某個master的所有slave的地址,sentinel會通過詢問master來得到這些slave的地址的
  • 每個sentinel通過向每個master和slave的釋出/訂閱頻道__sentinel__:hello每秒傳送一次訊息,來宣佈它的存在。
  • 每個sentinel也訂閱了每個master和slave的頻道__sentinel__:hello的內容,來發現未知的sentinel,當檢測到了新的sentinel,則將其加入到自身維護的master監控列表中。
  • 每個sentinel傳送的訊息中也包含了其當前維護的最新的master配置。如果某個sentinel發現自己的配置版本低於接收到的配置版本,則會用新的配置更新自己的master配置。
  • 在為一個master新增一個新的sentinel前,sentinel總是檢查是否已經有sentinel與新的sentinel的程序號或者是地址是一樣的。如果是那樣,這個sentinel將會被刪除,而把新的sentinel新增上去。
19、sentinel和redis身份驗證
  • 當一個master配置為需要密碼才能連線時,客戶端和slave在連線時都需要提供密碼
  • master通過requirepass設定自身的密碼,不提供密碼無法連線到這個master。slave通過masterauth來設定訪問master時的密碼
  • 但是當使用了sentinel時,由於一個master可能會變成一個slave,一個slave也可能會變成master,所以需要同時設定上述兩個配置項
20、Sentinel API
  • 在預設情況下, Sentinel 使用 TCP 埠 26379 (普通 Redis 伺服器使用的是 6379 )。Sentinel 接受 Redis 協議格式的命令請求,所以你可以使用 redis-cli 或者任何其他 Redis 客戶端來與 Sentinel 進行通訊。有兩種方式可以和 Sentinel 進行通訊:
    • 通過直接傳送命令來查詢被監視 Redis 伺服器的當前狀態, 以及 Sentinel 所知道的關於其他 Sentinel 的資訊, 諸如此類。
    • 使用釋出與訂閱功能, 通過接收 Sentinel 傳送的通知: 當執行故障轉移操作, 或者某個被監視的伺服器被判斷為主觀下線或者客觀下線時, Sentinel 就會發送相應的資訊。
  • Sentinel命令(即登入到sentinel節點後執行的命令,比如執行"redis-cli -h 192.168.10.203 -p 26379"命令後,才可以執行下面命令)
    • PING :返回 PONG
    • SENTINEL masters :列出所有被監視的主伺服器,以及這些主伺服器的當前狀態;
    • SENTINEL slaves <master name> :列出給定主伺服器的所有從伺服器,以及這些從伺服器的當前狀態;
    • SENTINEL get-master-addr-by-name <master name> : 返回給定名字的主伺服器的 IP 地址和埠號。 如果這個主伺服器正在執行故障轉移操作, 或者針對這個主伺服器的故障轉移操作已經完成, 那麼這個命令返回新的主伺服器的 IP 地址和埠號;
    • SENTINEL reset <pattern> : 重置所有名字和給定模式 pattern 相匹配的主伺服器。 pattern 引數是一個 Glob 風格的模式。 重置操作清楚主伺服器目前的所有狀態, 包括正在執行中的故障轉移, 並移除目前已經發現和關聯的, 主伺服器的所有從伺服器和 Sentinel ;
    • SENTINEL failover <master name> : 當主伺服器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移。 (不過發起故障轉移的 Sentinel 會向其他 Sentinel 傳送一個新的配置,其他 Sentinel 會根據這個配置進行相應的更新)
    • SENTINEL MONITOR <name> <ip> <port> <quorum> 這個命令告訴sentinel去監聽一個新的master
    • SENTINEL REMOVE <name> 命令sentinel放棄對某個master的監聽
    • SENTINEL SET <name> <option> <value> 這個命令很像Redis的CONFIG SET命令,用來改變指定master的配置。支援多個<option><value>。例如以下例項:SENTINEL SET objects-cache-master down-after-milliseconds 1000
  • 只要是配置檔案中存在的配置項,都可以用SENTINEL SET命令來設定。這個還可以用來設定master的屬性,比如說quorum(票數),而不需要先刪除master,再重新新增master。例如:SENTINEL SET objects-cache-master quorum 5
  • 客戶端可以通過SENTINEL get-master-addr-by-name <master name>獲取當前的主伺服器IP地址和埠號,以及SENTINEL slaves <master name>獲取所有的Slaves資訊。
21、增加或刪除Sentinel
  • 由於有sentinel自動發現機制,所以新增一個sentinel到你的叢集中非常容易,你所需要做的只是監控到某個Master上,然後新新增的sentinel就能獲得其他sentinel的資訊以及master所有的slaves。
  • 如果你需要新增多個sentinel,建議你一個接著一個新增,這樣可以預防網路隔離帶來的問題。你可以每個30秒新增一個sentinel。最後你可以用SENTINEL MASTER mastername來檢查一下是否所有的sentinel都已經監控到了master。
  • 刪除一個sentinel顯得有點複雜:因為sentinel永遠不會刪除一個已經存在過的sentinel,即使它已經與組織失去聯絡很久了
  • 要想刪除一個sentinel,應該遵循如下步驟:
    • 停止所要刪除的sentinel
    • 傳送一個SENTINEL RESET * 命令給所有其它的sentinel例項,如果你想要重置指定master上面的sentinel,只需要把*號改為特定的名字,注意,需要一個接一個發,每次傳送的間隔不低於30秒
    • 檢查一下所有的sentinels是否都有一致的當前sentinel數。使用SENTINEL MASTER mastername 來查詢
22、刪除舊master或者不可達slave
  • sentinel永遠會記錄好一個Master的slaves,即使slave已經與組織失聯好久了。這是很有用的,因為sentinel叢集必須有能力把一個恢復可用的slave進行重新配置。
  • 並且,failover後,失效的master將會被標記為新master的一個slave,這樣的話,當它變得可用時,就會從新master上覆制資料。
  • 然後,有時候你想要永久地刪除掉一個slave(有可能它曾經是個master),你只需要傳送一個SENTINEL RESET master命令給所有的sentinels,它們將會更新列表裡能夠正確地複製master資料的slave
23、sentinel.conf中的notification-script
  • 在sentinel.conf中可以配置多個sentinel notification-script <master name> <shell script-path>, 如sentinel notification-script mymaster ./check.sh 這個是在群集failover時會觸發執行指定的指令碼。指令碼的執行結果若為1,即稍後重試(最大重試次數為10)若為2,則執行結束。並且指令碼最大執行時間為60秒,超時會被終止執行
  • 目前會存在該指令碼被執行多次的問題,網上查詢資料獲得的解釋是:指令碼分為兩個級別, SENTINEL_LEADER 和 SENTINEL_OBSERVER ,前者僅由領頭 Sentinel 執行(一個 Sentinel),而後者由監視同一個 master 的所有 Sentinel 執行(多個 Sentinel)
24、Slave選舉與優先順序
  • 當一個sentinel準備好了要進行failover,並且收到了其他sentinel的授權,那麼就需要選舉出一個合適的slave來做為新的master。
  • slave的選舉主要會評估slave的以下幾個方面
    • 與master斷開連線的次數
    • Slave的優先順序
    • 資料複製的下標(用來評估slave當前擁有多少master的資料)
    • 程序ID
  • 如果一個slave與master失去聯絡超過10次,並且每次都超過了配置的最大失聯時間(down-after-milliseconds),如果sentinel在進行failover時發現slave失聯,那麼這個slave就會被sentinel認為不適合用來做新master的。更嚴格的定義是,如果一個slave持續斷開連線的時間超過(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state就會被認為失去選舉資格。
  • 符合上述條件的slave才會被列入master候選人列表,並根據以下順序來進行排序
    • sentinel首先會根據slaves的優先順序來進行排序,優先順序越小排名越靠前。
    • 如果優先順序相同,則檢視複製的下標,哪個從master接收的複製資料多,哪個就靠前。
    • 如果優先順序和下標都相同,就選擇程序ID較小的那個。
  • 一個redis無論是master還是slave,都必須在配置中指定一個slave優先順序。要注意到master也是有可能通過failover變成slave的。
  • 如果一個redis的slave優先順序配置為0,那麼它將永遠不會被選為master。但是它依然會從master那裡複製資料。
25、故障轉移
  • 所謂故障轉移就是當master宕機,選一個合適的slave來晉升為master的操作,redis-sentinel會自動完成這個,不需要我們手動來實現。
  • 一次故障轉移操作大致分為以下流程
    • 發現主伺服器已經進入客觀下線狀態。
    • 對我們的當前叢集進行自增, 並嘗試在這個叢集中當選。
    • 如果當選失敗, 那麼在設定的故障遷移超時時間的兩倍之後, 重新嘗試當選。 如果當選成功, 那麼執行以下步驟:
    • 選出一個從伺服器,並將它升級為主伺服器。
    • 向被選中的從伺服器傳送 SLAVEOF NO ONE 命令,讓它轉變為主伺服器。
    • 通過釋出與訂閱功能, 將更新後的配置傳播給所有其他 Sentinel , 其他 Sentinel 對它們自己的配置進行更新。
    • 向已下線主伺服器的從伺服器傳送 SLAVEOF 命令, 讓它們去複製新的主伺服器。
    • 當所有從伺服器都已經開始複製新的主伺服器時, 領頭 Sentinel 終止這次故障遷移操作。
  • 每當一個 Redis 例項被重新配置(reconfigured) —— 無論是被設定成主伺服器、從伺服器、又或者被設定成其他主伺服器的從伺服器 —— Sentinel 都會向被重新配置的例項傳送一個 CONFIG REWRITE 命令, 從而確保這些配置會持久化在硬盤裡。
  • Sentinel 使用以下規則來選擇新的主伺服器
    • 在失效主伺服器屬下的從伺服器當中, 那些被標記為主觀下線、已斷線、或者最後一次回覆 PING 命令的時間大於五秒鐘的從伺服器都會被淘汰。
    • 在失效主伺服器屬下的從伺服器當中, 那些與失效主伺服器連線斷開的時長超過 down-after 選項指定的時長十倍的從伺服器都會被淘汰。
    • 在經歷了以上兩輪淘汰之後剩下來的從伺服器中, 我們選出複製偏移量(replication offset)最大的那個從伺服器作為新的主伺服器; 如果複製偏移量不可用, 或者從伺服器的複製偏移量相同, 那麼帶有最小執行 ID 的那個從伺服器成為新的主伺服器。
  • Sentinel 自動故障遷移的一致性特質
    • Sentinel 自動故障遷移使用 Raft 演算法來選舉領頭(leader) Sentinel , 從而確保在一個給定的紀元(epoch)裡, 只有一個領頭產生。
    • 這表示在同一個紀元中, 不會有兩個 Sentinel 同時被選中為領頭, 並且各個 Sentinel 在同一個紀元中只會對一個領頭進行投票。
    • 更高的配置紀元總是優於較低的紀元, 因此每個 Sentinel 都會主動使用更新的紀元來代替自己的配置。
    • 簡單來說, 可以將 Sentinel 配置看作是一個帶有版本號的狀態。 一個狀態會以最後寫入者勝出(last-write-wins)的方式(也即是,最新的配置總是勝出)傳播至所有其他 Sentinel
    • 舉個例子, 當出現網路分割(network partitions)時, 一個 Sentinel 可能會包含了較舊的配置, 而當這個 Sentinel 接到其他 Sentinel 發來的版本更新的配置時, Sentinel 就會對自己的配置進行更新。
    • 如果要在網路分割出現的情況下仍然保持一致性, 那麼應該使用 min-slaves-to-write 選項, 讓主伺服器在連線的從例項少於給定數量時停止執行寫操作, 與此同時, 應該在每個執行 Redis 主伺服器或從伺服器的機器上執行 Redis Sentinel 程序。
  • Sentinel 狀態的持久化
    • Sentinel 的狀態會被持久化在 Sentinel 配置檔案裡面。每當 Sentinel 接收到一個新的配置, 或者當領頭 Sentinel 為主伺服器建立一個新的配置時, 這個配置會與配置紀元一起被儲存到磁盤裡面。這意味著停止和重啟 Sentinel 程序都是安全的
    • Sentinel 在非故障遷移的情況下對例項進行重新配置
    • 即使沒有自動故障遷移操作在進行, Sentinel 總會嘗試將當前的配置設定到被監視的例項上面。 特別是:
    • 根據當前的配置, 如果一個從伺服器被宣告為主伺服器, 那麼它會代替原有的主伺服器, 成為新的主伺服器, 並且成為原有主伺服器的所有從伺服器的複製物件。
    • 那些連線了錯誤主伺服器的從伺服器會被重新配置, 使得這些從伺服器會去複製正確的主伺服器。
    • 不過, 在以上這些條件滿足之後, Sentinel 在對例項進行重新配置之前仍然會等待一段足夠長的時間, 確保可以接收到其他 Sentinel 發來的配置更新, 從而避免自身因為儲存了過期的配置而對例項進行了不必要的重新配置。
  • 總結來說,故障轉移分為三個步驟
    • 從下線的主服務的所有從服務裡面挑選一個從服務,將其轉成主服務
      • sentinel狀態資料結構中儲存了主服務的所有從服務資訊,領頭sentinel按照如下的規則從從服務列表中挑選出新的主服務;
        • 刪除列表中處於下線狀態的從服務;
        • 刪除最近5秒沒有回覆過領頭sentinel info資訊的從服務;
        • 刪除與已下線的主服務斷開連線時間超過 down-after-milliseconds*10毫秒的從服務,這樣就能保留從的資料比較新(沒有過早的與主斷開連線);
        • 領頭sentinel從剩下的從列表中選擇優先順序高的,如果優先順序一樣,選擇偏移量最大的(偏移量大說明覆制的資料比較新),如果偏移量一樣,選擇執行id最小的從服務。
    • 已下線主服務的所有從服務改為複製新的主服務
      • 挑選出新的主服務之後,領頭sentinel 向原主服務的從服務傳送 slaveof 新主服務 的命令,複製新master。
    • 將已下線的主服務設定成新的主服務的從服務,當其回覆正常時,複製新的主服務,變成新的主服務的從服務同理,當已下線的服務重新上線時,sentinel會向其傳送slaveof命令,讓其成為新主的從。
  • 溫馨提示:還可以向任意sentinel發生sentinel failover <masterName> 進行手動故障轉移,這樣就不需要經過上述主客觀和選舉的過程。
  • sentinel.conf檔案配置引數解釋
sentinel monitor mymaster 192.168.10.202 6379 2
"""
Sentine監聽的maste地址,第一個引數是給master起的名字,第二個引數為master IP,第三個為master埠,第四個為當該master掛了的時候,若想將該master判為失效,
在Sentine叢集中必須至少2個Sentine同意才行,只要該數量不達標,則就不會發生故障遷移。也就是說只要有2個sentinel認為master下線,就認為該master客觀下線,
啟動failover並選舉產生新的master。通常最後一個引數不能多於啟動的sentinel例項數。
 
這個配置是sentinel需要監控的master/slaver資訊,格式為sentinel monitor <mastername> <masterIP> <masterPort> <quorum> 
其中<quorum>應該小於叢集中slave的個數,當失效的節點數超過了<quorum>,則認為整個體系結構失效
 
不過要注意, 無論你設定要多少個 Sentinel 同意才能判斷一個伺服器失效, 一個 Sentinel 都需要獲得系統中多數(majority) Sentinel 的支援, 才能發起一次自動故障遷移,
並預留一個給定的配置紀元 (configuration Epoch ,一個配置紀元就是一個新主伺服器配置的版本號)。
  
換句話說, 在只有少數(minority) Sentinel 程序正常運作的情況下, Sentinel 是不能執行自動故障遷移的。
"""
sentinel down-after-milliseconds mymaster 30000
"""
表示master被當前sentinel例項認定為失效的間隔時間。
master在多長時間內一直沒有給Sentine返回有效資訊,則認定該master主觀下線。也就是說如果多久沒聯絡上redis-servevr,認為這個redis-server進入到失效(SDOWN)狀態。
  
如果伺服器在給定的毫秒數之內, 沒有返回 Sentinel 傳送的 PING 命令的回覆, 或者返回一個錯誤, 那麼 Sentinel 將這個伺服器標記為主觀下線(subjectively down,簡稱 SDOWN )。
不過只有一個 Sentinel 將伺服器標記為主觀下線並不一定會引起伺服器的自動故障遷移: 只有在足夠數量的 Sentinel 都將一個伺服器標記為主觀下線之後, 伺服器才會被標記為客觀下線
(objectively down, 簡稱 ODOWN ), 這時自動故障遷移才會執行。
將伺服器標記為客觀下線所需的 Sentinel 數量由對主伺服器的配置決定。
"""
sentinel parallel-syncs mymaster 2
"""
當在執行故障轉移時,設定幾個slave同時進行切換master,該值越大,則可能就有越多的slave在切換master時不可用,可以將該值設定為1,即一個一個來,這樣在某個
slave進行切換master同步資料時,其餘的slave還能正常工作,以此保證每次只有一個從伺服器處於不能處理命令請求的狀態。
  
parallel-syncs 選項指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。
  
如果從伺服器被設定為允許使用過期資料集(參見對 redis.conf 檔案中對 slave-serve-stale-data 選項的說明), 那麼你可能不希望所有從伺服器都在同一時間向新的主伺服器傳送同步請求,
因為儘管複製過程的絕大部分步驟都不會阻塞從伺服器, 但從伺服器在載入主伺服器發來的 RDB 檔案時, 仍然會造成從伺服器在一段時間內不能處理命令請求: 如果全部從伺服器一起對新的主
伺服器進行同步, 那麼就可能會造成所有從伺服器在短時間內全部不可用的情況出現。
 
當新master產生時,同時進行"slaveof"到新master並進行"SYNC"的slave個數。 
預設為1,建議保持預設值 
在salve執行salveof與同步時,將會終止客戶端請求。 
此值較大,意味著"叢集"終止客戶端請求的時間總和和較大。 
此值較小,意味著"叢集"在故障轉移期間,多個salve向客戶端提供服務時仍然使用舊資料。 
"""
sentinel can-failover mymaster yes
"""
在sentinel檢測到O_DOWN後,是否對這臺redis啟動failover機制
"""
sentinel auth-pass mymaster 20180408
"""
設定sentinel連線的master和slave的密碼,這個需要和redis.conf檔案中設定的密碼一樣
"""
sentinel failover-timeout mymaster 180000
"""
failover過期時間,當failover開始後,在此時間內仍然沒有觸發任何failover操作,當前sentinel將會認為此次failoer失敗。 
執行故障遷移超時時間,即在指定時間內沒有大多數的sentinel 反饋master下線,該故障遷移計劃則失效
"""
sentinel config-epoch mymaster 0
"""
選項指定了在執行故障轉移時, 最多可以有多少個從伺服器同時對新的主伺服器進行同步。這個數字越小, 完成故障轉移所需的時間就越長。
"""
sentinel notification-script mymaster /var/redis/notify.sh
"""
當failover時,可以指定一個"通知"指令碼用來告知當前叢集的情況。
指令碼被允許執行的最大時間為60秒,如果超時,指令碼將會被終止(KILL)
"""
sentinel leader-epoch mymaster 0
"""
同時一時間最多0個slave可同時更新配置,建議數字不要太大,以免影響正常對外提供服務。
"""