哨兵(Sentinel)是redis 的高可用性解決方案,前面我們講的主從複製它是高可用的基礎,但是單純的主從複製需要人工介入才能完成故障轉移,哨兵可以解決這個問題,在主從複製情況下,當主節點發生故障時,哨兵可以自動的發現故障並且完成故障轉移,實現真正的 redis 高可用。在哨兵叢集中,哨兵會監視所有的 redis 伺服器和其他 sentinel 節點狀態,及時發現故障完成轉移,從而確保 redis 的高可用。
儘管哨兵本質上也是 Redis 服務,但它提供了與普通 Redis 服務不同的功能。哨兵是分散式架構,因為你要確保redis 高可用,首先需要確保自己高可用,所以如果我們需要搭建哨兵的話,最少需要部署三個實例,最好是奇數個,因為在後續的故障轉移中會涉及到投票。
哨兵的設定檔我們可以在redis 的GitHub 專案下下載,在專案下方有一個叫做sentinel.conf 的文件,可以使用它作為我們哨兵的設定模板,當然你也可以使用redis.conf配置文件,只需要添加哨兵相關配置就好了。
哨兵相關的組態項目不多,主要有以下組組態項目:
// 端口号,默认是 redis 实例+20000,所以我们沿用这个规则就好了 port 26379 // 是否守护进程运行 daemonize yes // 日志存放的位置,这个非常重要,通过日志可以查看故障转移的过程 logfile "26379.log" // 监视一个名为 mymaster(自定义) 的 redis 主服务器, 这个主服务器的 IP 地址为 127.0.0.1 , 端口号为 6379 , // 最后面的 2 代表着至少有两个哨兵认为主服务器出现故障才会进行故障转移,否则认定主服务未失效 sentinel monitor mymaster 127.0.0.1 6379 2 // 哨兵判断服务器失效的响应时间,超过这个时间未接收到服务器的回应,就认为该服务器失效了 sentinel down-after-milliseconds mymaster 30000 // 完成故障转移之后,最多多少个从服务器可以同时发起数据复制,数字越小,说明完成全部从服务数据复制的时间越长 // 数字越大,对主服务器的压力就变大了 sentinel parallel-syncs mymaster 1 // 故障转移超时时间 sentinel failover-timeout mymaster 180000
對於每個Sentinel 實例配置除了port 和logfile 不同之外,其他組態項目都是一樣的。修改好設定後,我們可以使用 ./redis-sentinel sentinel.conf 指令來啟動哨兵,指令跟redis 實例啟動差不多,因為哨兵也是redis 實例,所以我們可以使用./redis-cli -p 26379 info sentinel 指令查看目前的哨兵訊息,如下圖所示:
哨兵訊息
問題:如何在只配置master 伺服器的情況下,發現從伺服器和其他Sentinel ?
從伺服器的發現,Sentinel 可以透過詢問主伺服器來獲取從伺服器的信息,對於發現其他Sentinel 節點,則透過發布與訂閱功能實現,透過向頻道 sentinel:hello 發送訊息來實現的,主要有以下兩步驟:
1、每個Sentinel 每2 秒會透過發布與訂閱功能向所有的主服務和從伺服器的sentinel:hello 頻道發送一條訊息, 訊息中包含了 Sentinel的IP 位址、連接埠號碼和運行ID (runid)
2、每個Sentinel 都訂閱了所有被它監視的主伺服器和從伺服器的sentinel:hello 頻道, 尋找之前未出現過的sentinel ( looking for unknown sentinels)。當一個Sentinel 發現一個新的Sentinel 時, 它會將新的Sentinel 加入一個清單中, 這個清單保存了Sentinel 已知的, 監視同一個主伺服器的所有其他Sentinel
故障轉移是哨兵的主要工作,這背後的實作邏輯也是非常的複雜,具體的實作邏輯也請查看相關書籍,我對哨兵的故障轉移總結了以下三點:
每個Sentinel 節點每隔1 秒鐘對主節點、從節點、其他Sentinel 節點發送ping 指令做心跳偵測,來判斷伺服器的狀態。
節點也會對Sentinel 進行相應的回复,在這些回復中,以下三個回復是有效回复:
返回PONG
返回-LOADING
返回-MASTERDOWN
如果節點在哨兵設定檔設定的master-down-after-milliseconds選項的值內,一直沒有哪怕一次有效回复,那麼Sentinel 會把該伺服器標記為下線狀態,我們把這種下線稱為主觀下線,也就是說只有這個sentinel 認為該伺服器是下線狀態。
如果被主觀下線的伺服器是主伺服器時,sentinel 為了確認這個主伺服器是否真的下線,該Sentinel 會向其他的同樣監聽主伺服器的 Sentinel 進行詢問,看他們是否也認為主伺服器進入下線狀態,當有足夠多的Sentinel 都認為主伺服器下線時,該Sentinel 會將主伺服器判斷為客觀下線,這是真正的下線了,並且會對它進行故障轉移操作。
故障轉移並不是所有的sentinel 共同完成,而是選舉出一台sentinel 節點作為領導者來完成這次故障轉移,所以當主伺服器被標記為客觀下線時,sentinel 之間就會透過Raft 演算法選出一個領導者來完成故障轉移工作。大致規則和方法如下,redis進行sentinel的領頭選舉
所有在線的sentinel 都有資格被選為領導者,也就是說每個sentinel 都有成為領導者的機會
當sentinel 標記主伺服器為主觀下線時,會傳送sentinel is-master-down-by-addr 指令,要求將自己設定為領導者
收到指令的Sentinel 節點,採用先到先得的規則,如果沒有同意過其他Sentinel 節點的sentinel is-master-down-by-addr 指令,將同意該請求,否則拒絕
如果該Sentinel 節點發現自己的票數已經超過半數,那麼它將成為領導者
如果在規定時間內,沒有選出sentinel 領導者,那麼將在一段時間後再次選舉,知道選出sentinel 領導者為止。
選舉出來的sentinel 領導者將完成剩餘的故障轉移工作,故障轉移主要有以下三個步驟:
(1)挑選出新的主伺服器
在已下線的主伺服器的所有從伺服器中,挑選出一個從伺服器,並將其轉換為主伺服器,選擇新的主伺服器的規則如下:
在失效主伺服器屬下的從伺服器當中, 那些被標記為主觀下線、已斷線、或最後一次回覆PING 指令的時間大於五秒鐘的從伺服器都會被淘汰
在失效主伺服器屬下的從伺服器當中, 那些與失效主伺服器連接斷開的時長超過down-after 選項指定的時長十倍的從伺服器都會被淘汰
在經歷了以上兩輪淘汰之後剩下來的從伺服器中, 選出複製偏移量(replication offset)最大的那個從伺服器作為新的主伺服器;如果複製偏移量不可用, 或者從伺服器的複製偏移量相同, 那麼帶有最小運行ID 的那個從伺服器成為新的主伺服器
對挑選出來的從伺服器執行slaveof no one 指令,使其成為主節點。
(2)修改其他從伺服器的複製目標
當新的主伺服器出現後,sentinel 的領導者下一步需要做的就是,讓其他從伺服器去複製新的主伺服器,透過向其他從伺服器發送slaveof new_master port 指令來完成,複製規則和設定檔的parallel-syncs 參數有關
(3)將舊的主伺服器變成從伺服器
故障轉移操作最後要做的就是將已下線的主伺服器設定為新的主服務的從伺服器,並保持對其關注,等它恢復後命令它去複製新的主節點。
以上是Redis的哨兵故障轉移原理是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!