聊聊Redis Sentinel

Redis Sentinel 是一個分布式系統, 你可以在一個架構中運行多個 Sentinel 進程(progress), 這些進程使用流言協議(gossip protocols)來接收關于主服務器是否下線的信息, 并使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪個從服務器作為新的主服務器。

Redis 的 Sentinel 系統用于管理多個Redis 服務器(instance), 該系統執行以下三個任務:

  • 監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。
  • 提醒(Notification): 當被監控的某個 Redis 服務器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。
  • 自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主服務器的其中一個從服務器升級為新的主服務器, 并讓失效主服務器的其他從服務器改為復制新的主服務器; 當客戶端試圖連接失效的主服務器時, 集群也會向客戶端返回新主服務器的地址, 使得集群可以使用新主服務器代替失效服務器。

Redis Sentinel 是一個分布式系統, 你可以在一個架構中運行多個 Sentinel 進程(progress), 這些進程使用流言協議(gossip protocols)來接收關于主服務器是否下線的信息, 并使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪個從服務器作為新的主服務器。

雖然 Redis Sentinel 釋出為一個單獨的可執行文件 redis-sentinel , 但實際上它只是一個運行在特殊模式下的 Redis 服務器, 你可以在啟動一個普通 Redis 服務器時通過給定 –sentinel 選項來啟動 Redis Sentinel 。

啟動 Sentinel

對于 redis-server 程序, 你可以用以下命令來啟動一個運行在 Sentinel 模式下的 Redis 服務器:

redis-server /path/to/sentinel.conf --sentinel

啟動 Sentinel 實例必須指定相應的配置文件, 系統會使用配置文件來保存 Sentinel 的當前狀態, 并在 Sentinel 重啟時通過載入配置文件來進行狀態還原。

如果啟動 Sentinel 時沒有指定相應的配置文件, 或者指定的配置文件不可寫(not writable), 那么 Sentinel 會拒絕啟動。

配置 Sentinel

運行一個 Sentinel 所需的最少配置如下所示:

sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 15000
sentinel parallel-syncs mymaster 1

第一行配置指示 Sentinel 去監視一個名為 mymaster 的主服務器, 這個主服務器的 IP 地址為 127.0.0.1 , 端口號為 6379 , 而將這個主服務器判斷為失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數量不達標,自動故障遷移就不會執行)。

不過要注意, 無論你設置要多少個 Sentinel 同意才能判斷一個服務器失效, 一個 Sentinel 都需要獲得系統中多數(majority) Sentinel 的支持, 才能發起一次自動故障遷移, 并預留一個給定的配置紀元 (configuration Epoch ,一個配置紀元就是一個新主服務器配置的版本號)。

換句話說, 在只有少數(minority) Sentinel 進程正常運作的情況下, Sentinel 是不能執行自動故障遷移的。

各個選項的功能如下:

  • down-after-milliseconds 選項指定了 Sentinel 認為服務器已經斷線所需的毫秒數。

    如果服務器在給定的毫秒數之內, 沒有返回 Sentinel 發送的 PING 命令的回復, 或者返回一個錯誤, 那么 Sentinel 將這個服務器標記為主觀下線(subjectively down,簡稱 SDOWN )。

    不過只有一個 Sentinel 將服務器標記為主觀下線并不一定會引起服務器的自動故障遷移: 只有在足夠數量的 Sentinel 都將一個服務器標記為主觀下線之后, 服務器才會被標記為客觀下線(objectively down, 簡稱 ODOWN ), 這時自動故障遷移才會執行。

    將服務器標記為客觀下線所需的 Sentinel 數量由對主服務器的配置決定。

  • parallel-syncs 選項指定了在執行故障轉移時,最多可以有多少個從服務器同時對新的主服務器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。

    如果從服務器被設置為允許使用過期數據集(參見對 redis.conf 文件中對 slave-serve-stale-data 選項的說明), 那么你可能不希望所有從服務器都在同一時間向新的主服務器發送同步請求, 因為盡管復制過程的絕大部分步驟都不會阻塞從服務器, 但從服務器在載入主服務器發來的 RDB 文件時, 仍然會造成從服務器在一段時間內不能處理命令請求: 如果全部從服務器一起對新的主服務器進行同步, 那么就可能會造成所有從服務器在短時間內全部不可用的情況出現。

    你可以通過將這個值設為 1 來保證每次只有一個從服務器處于不能處理命令請求的狀態。

主觀下線和客觀下線

前面說過, Redis 的 Sentinel 中關于下線(down)有兩個不同的概念:

  • 主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個 Sentinel 實例對服務器做出的下線判斷。
  • 客觀下線(Objectively Down, 簡稱 ODOWN)指的是多個 Sentinel 實例在對同一個服務器做出 SDOWN 判斷, 并且通過 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服務器下線判斷。 (一個 Sentinel 可以通過向另一個 Sentinel 發送 SENTINEL is-master-down-by-addr 命令來詢問對方是否認為給定的服務器已下線。)

如果一個服務器沒有在 master-down-after-milliseconds 選項所指定的時間內, 對向它發送 PING 命令的 Sentinel 返回一個有效回復(valid reply), 那么 Sentinel 就會將這個服務器標記為主觀下線。

服務器對 PING 命令的有效回復可以是以下三種回復的其中一種:

  • 返回 +PONG 。
  • 返回 -LOADING 錯誤。
  • 返回 -MASTERDOWN 錯誤。

如果服務器返回除以上三種回復之外的其他回復, 又或者在指定時間內沒有回復 PING 命令, 那么 Sentinel 認為服務器返回的回復無效(non-valid)。

注意, 一個服務器必須在 master-down-after-milliseconds 毫秒內, 一直返回無效回復才會被 Sentinel 標記為主觀下線。

舉個例子, 如果 master-down-after-milliseconds 選項的值為 30000 毫秒(30 秒), 那么只要服務器能在每 29 秒之內返回至少一次有效回復, 這個服務器就仍然會被認為是處于正常狀態的。

從主觀下線狀態切換到客觀下線狀態并沒有使用嚴格的法定人數算法(strong quorum algorithm), 而是使用了流言協議: 如果 Sentinel 在給定的時間范圍內, 從其他 Sentinel 那里接收到了足夠數量的主服務器下線報告, 那么 Sentinel 就會將主服務器的狀態從主觀下線改變為客觀下線。 如果之后其他 Sentinel 不再報告主服務器已下線, 那么客觀下線狀態就會被移除。

客觀下線條件只適用于主服務器: 對于任何其他類型的 Redis 實例, Sentinel 在將它們判斷為下線前不需要進行協商, 所以從服務器或者其他 Sentinel 永遠不會達到客觀下線條件。

只要一個 Sentinel 發現某個主服務器進入了客觀下線狀態, 這個 Sentinel 就可能會被其他 Sentinel 推選出, 并對失效的主服務器執行自動故障遷移操作。

每個 Sentinel 都需要定期執行的任務

  • 每個 Sentinel 以每秒鐘一次的頻率向它所知的主服務器、從服務器以及其他 Sentinel 實例發送一個 PING 命令。
  • 如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 那么這個實例會被 Sentinel 標記為主觀下線。 一個有效回復可以是: +PONG 、 -LOADING 或者 -MASTERDOWN 。
  • 如果一個主服務器被標記為主觀下線, 那么正在監視這個主服務器的所有 Sentinel 要以每秒一次的頻率確認主服務器的確進入了主觀下線狀態。
  • 如果一個主服務器被標記為主觀下線, 并且有足夠數量的 Sentinel (至少要達到配置文件指定的數量)在指定的時間范圍內同意這一判斷, 那么這個主服務器被標記為客觀下線。
  • 在一般情況下, 每個 Sentinel 會以每 10 秒一次的頻率向它已知的所有主服務器和從服務器發送 INFO 命令。 當一個主服務器被 Sentinel 標記為客觀下線時, Sentinel 向下線主服務器的所有從服務器發送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
  • 當沒有足夠數量的 Sentinel 同意主服務器已經下線, 主服務器的客觀下線狀態就會被移除。 當主服務器重新向 Sentinel 的 PING 命令返回有效回復時, 主服務器的主管下線狀態就會被移除。

自動發現 Sentinel 和從服務器

一個 Sentinel 可以與其他多個 Sentinel 進行連接,各個 Sentinel 之間可以互相檢查對方的可用性,并進行信息交換。

你無須為運行的每個 Sentinel 分別設置其他 Sentinel 的地址, 因為 Sentinel 可以通過發布與訂閱功能來自動發現正在監視相同主服務器的其他 Sentinel , 這一功能是通過向頻道 sentinel:hello 發送信息來實現的。

與此類似, 你也不必手動列出主服務器屬下的所有從服務器, 因為 Sentinel 可以通過詢問主服務器來獲得所有從服務器的信息。

  • 每個 Sentinel 會以每兩秒一次的頻率, 通過發布與訂閱功能, 向被它監視的所有主服務器和從服務器的 sentinel:hello 頻道發送一條信息, 信息中包含了 Sentinel 的 IP 地址、端口號和運行 ID (runid)。
  • 每個 Sentinel 都訂閱了被它監視的所有主服務器和從服務器的 sentinel:hello 頻道, 查找之前未出現過的 sentinel (looking for unknown sentinels)。 當一個 Sentinel 發現一個新的 Sentinel 時, 它會將新的 Sentinel 添加到一個列表中, 這個列表保存了 Sentinel 已知的, 監視同一個主服務器的所有其他 Sentinel 。
  • Sentinel 發送的信息中還包括完整的主服務器當前配置(configuration)。 如果一個 Sentinel 包含的主服務器配置比另一個 Sentinel 發送的配置要舊, 那么這個 Sentinel 會立即升級到新配置上。
  • 在將一個新 Sentinel 添加到監視主服務器的列表上面之前, Sentinel 會先檢查列表中是否已經包含了和要添加的 Sentinel 擁有相同運行 ID 或者相同地址(包括 IP 地址和端口號)的 Sentinel , 如果是的話, Sentinel 會先移除列表中已有的那些擁有相同運行 ID 或者相同地址的 Sentinel , 然后再添加新 Sentinel 。

故障轉移

每當一個 Redis 實例被重新配置(reconfigured) —— 無論是被設置成主服務器、從服務器、又或者被設置成其他主服務器的從服務器 —— Sentinel 都會向被重新配置的實例發送一個 CONFIG REWRITE 命令, 從而確保這些配置會持久化在硬盤里。

Sentinel 使用以下規則來選擇新的主服務器:

  • 在失效主服務器屬下的從服務器當中, 那些被標記為主觀下線、已斷線、或者最后一次回復 PING 命令的時間大于五秒鐘的從服務器都會被淘汰。
  • 在失效主服務器屬下的從服務器當中, 那些與失效主服務器連接斷開的時長超過 down-after 選項指定的時長十倍的從服務器都會被淘汰。
  • 在經歷了以上兩輪淘汰之后剩下來的從服務器中, 我們選出復制偏移量(replication offset)最大的那個從服務器作為新的主服務器; 如果復制偏移量不可用, 或者從服務器的復制偏移量相同, 那么帶有最小運行 ID 的那個從服務器成為新的主服務器。

Sentinel 狀態的持久化

Sentinel 的狀態會被持久化在 Sentinel 配置文件里面。

每當 Sentinel 接收到一個新的配置, 或者當領頭 Sentinel 為主服務器創建一個新的配置時, 這個配置會與配置紀元一起被保存到磁盤里面。

這意味著停止和重啟 Sentinel 進程都是安全的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Redis 2.8版開始正式提供名為Sentinel的主從切換方案,Sentinel用于管理多個Redis服務器實...
    183207efd207閱讀 616評論 0 1
  • 1. 高可用性 redis sentinel 官方文檔redis sentinel 中文文檔 前面說到使用主從備份...
    我不是李小龍閱讀 714評論 0 1
  • 得念失念,憑誰顧. 莊周夢蝶,三世空. “滴噠,滴噠” 我雙手捧著一杯檸檬水,靜靜的看著坐在對面的女孩。 她已經有...
    沐xin然閱讀 332評論 0 2
  • 薛之謙在上海演唱會上為前妻唱了首《安和橋》,很孩子氣,也很浪漫,因為是孩子氣的浪漫,所以特別浪漫。說他孩子氣...
    霷揚閱讀 431評論 0 1
  • 1. “棺有靈來墓有魂,無棺野墓不如墳。” 作為最后一代“守棺人”,爺爺在我還小的時候就一直把這句話當成兒歌來哄我...
    國風千尋閱讀 615評論 6 10