【Redis】哨兵模式

紙上得來終覺淺,絕知此事要躬行。html

哨兵模式

Sentinel是Redis的高可用的解決方案,有多個Sentinel實例構成Sentinel系統。系統能夠監視任意多個主服務器以及這些主服務器下的從服務器,當被監視的主服務器進入下線狀態時,自動將下線的主服務屬下的從服務器升級爲新的主服務器,而後由新的主服務器替代下線主服務器繼續處理命令請求。redis

下圖展現了一個Sentinel系統監視服務器的例子:sql

Sentinel系統監視服務器

假設此時,主服務器Master因爲某種緣由意外宕機下線,那麼從服務器slave對主服務器的複製操做將被終止。而且Sentinel系統會察覺到Master已經下線。服務器

Master宕機

當Master長時間處於下線,Sentinel系統將會對Master進行執行故障轉移,以後Sentinel系統會在Master屬下的從服務器挑選出一個做爲新的主服務器,而且先其餘slave發送複製指令,讓他們重新的服務器開始複製。網絡

當某個時間舊Master從新上線時,Sentinel系統會將它設置爲新服務器的從服務器。異步

Master從新上線

注意:以上的Sentinel系統中任意一臺Sentinel都會監視全部的服務器3d

啓動 Sentinel

  • 對於 redis-sentinel 程序, 你能夠用如下命令來啓動 Sentinel 系統:
redis-sentinel /path/to/sentinel.conf
  • 對於 redis-server 程序, 你能夠用如下命令來啓動一個運行在 Sentinel 模式下的 Redis 服務器:
redis-server /path/to/sentinel.conf --sentinel

配置Sentinel

配置項 示例 說明
sentinel auth-pass
<服務器名稱>
sentinel auth-pass mymaster
ydongy
鏈接服務器口令
sentinel down-after-milliseconds
<自定義服務名稱><主機地址><端口><主從服務器總量>
sentinel monitor mymaster
1127.0.0.1 6379 1
設置哨兵監聽的主服務器信息,最後的參數決定了最終參與選舉的服務器數量
sentinel parallel-syncs
<服務名稱><服務器數(整數)>
sentinel parallel-syncs
mymaster 1
指定同時進行主從的slave數量,數值越大,要求網絡資源越高,要求約小,同步時間約長
sentinel failover-timeout
<服務名稱><毫秒數(整數)>
sentinel failover-timeout
mymaster 9000
指定出現故障後,故障切換的最大超時時間,超過該值,認定切換失敗,默認3分鐘
sentinel notification-script
<服務名稱><腳本路徑>
服務器沒法正常聯通時,設定的執行腳本,一般調試使用。

工做原理

1. 創建與服務器之間的鏈接

Sentinel啓動時會經過配置建立與指定主服務器的網絡鏈接,Sentinel將成爲主服務器的客戶端,能夠向主服務器發送命令,而且從命令的回覆中獲取相關服務器的信息。調試

對於每一個被Sentinel監視和主服務器來講,Sentinel會建立兩個異步網絡鏈接:code

  • 命令鏈接:專門發送命令給主服務器
  • 訂閱鏈接:專門訂閱主服務器的__Sentinel__:hello頻道

Sentinel默認會每十秒發送一次info命令,經過分析info命令的回覆獲取主服務器當前信息以及根據當前主服務器下的從服務器ipport地址信息,自動的發現從服務器。並保存在一個鍵爲:ip:port,值爲從服務器的實例結構的字典當中。一樣也會建立鏈接到從服務器的命令鏈接和訂閱鏈接。整個結構以下圖:server

在建立命令以後,Sentinel在默認狀況下,一樣也會每十秒一次的頻率經過命令鏈接向從服務器發送info命令,得到從服務器的詳細信息,根據這些信息,會對以前的從服務器實例結構進行更新。

2. 發送消息

在默認狀況下,Sentinel會以每兩秒一次的頻率,經過命令鏈接向全部被監視的主服務器和從服務器發送命令到__Sentinel__:hello頻道:

PUBLISH __Sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"
  • s_表示Sentinel自己信息
  • m_表示主服務的信息

經過命令鏈接__Sentinel__:hello頻道發送的消息,同時又會被訂閱鏈接從頻道中獲取出來,包括其餘在__Sentinel__:hello頻道中的Sentinel一樣也會接受到該信息(包括髮送者本身)。舉個例子,以下圖:

因爲每一個Sentinel都會發送消息,也就是說任何一個Sentinel都會接受到本身以及其餘Sentinel發送的消息,而且消息中含有Sentinel的信息,因此每一個Sentinel都會把本身以及其餘的Sentinel的信息保存在字典當中,鍵是ip:port,值是一個Sentinel實例結構。當之後每次接受到消息,更新保存的信息,防止有宕機的Sentinel或者新添加的Sentinel。

3. 建立與其餘Sentinel的命令鏈接

上一節說了在Sentinel向服務器經過命令鏈接發送信息,會被訂閱鏈接接受到消息,若是發現一個字典當中不存在當前Sentinel,會爲當前Sentinel建立相應的實例結構。

其實,同時會建立一個命令鏈接,而新Sentinel也會鏈接到這個Sentinel,至關於兩兩相連,以下圖所示:

4. 主觀下線

在默認狀況下,Sentinel會一秒一次的頻率向全部與它建立命令鏈接的服務器(包括:主服務器,從服務器,其餘Sentinel)發送PING命令,經過實例的返回恢復來判斷實例時候在線。

發送PING命令回覆分爲兩種:

  • 有效恢復:
    • +PONG
    • -LOADING
    • -MASTERDOWN
  • 無效恢復:不包含以上三種,或者返回其餘恢復

最開始啓動Sentinel的時候,咱們在配置文件中配置了一個down-after-milliseconds的參數,若是在當前參數範圍內沒有一次有效恢復,那麼當前Sentinel就認爲該服務器主觀下線,固然還可能存在多個Sentinel配置的時間大小不一樣,例如:

  • Sentinel-1
sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 60000
  • Sentinel-2
sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 20000

那麼當master的斷線時長超過20000毫秒以後,sentinel-2會判斷該服務器主觀下線,可是Sentinel-1認爲master處於在線狀態,以後當master斷線60000毫秒以後,Sentinel-1和Sentinel-2才都會認爲master進入主觀下線狀態。結合圖查看一下:

5. 客觀下線

當Sentinel將一個主服務器判斷爲主觀下線以後,爲了確保主服務器真正的下線,當前的Sentinel會先其餘監視該服務器的Sentinel進行詢問,看他們是否也認爲主服務器進入下線狀態,當Sentinel從其餘Sentinel哪裏接受到足夠數量的如下線判斷以後,Sentinel就會將服務斷定爲客觀下線,以後便進行故障轉移。

經過發送以下命令進行詢問其餘Sentinel:

SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
  • ip:主服務器IP地址
  • port:主服務器端口號
  • current_epoch:Sentinel當前的配置紀元
  • runid:能夠爲*表示僅僅檢測主服務器的客觀下線狀態,或者是Sentinel的運行ID用於選舉領頭Sentinel

接受源Sentinel命令回覆:

  • down_state:返回接受者Sentinel的對主服務器的檢查結果,1:下線,0:未下線
  • leader_runid:能夠是*表示僅僅檢測主服務器的下線狀態,或者接受者Sentinel的運行ID用於選舉領頭Sentinel
  • leader_epoch:接受者Sentinel的認爲領頭Sentinel的配置紀元

例如:

1
*
0

那麼說明接受者Sentinel也贊成主服務已下線。整個過程如圖所示:

客觀下線的判斷條件是經過配置中sentinel monitor host6379 127.0.0.1 6379 2最後一個參數決定,例如當前爲2,意味着若是全部的Sentinel只要有兩個認爲主服務器下線,那麼當前Sentinel纔會將主服務判斷爲客觀下線。

5. 選舉領頭Sentinel

在一個主服務器被判斷爲客觀下線時,監視這個下線主服務器的一個Sentinel會進行協商,選出一個領頭Sentinel去進行故障轉移操做。

選取領頭Sentinel規則和方法:

  • 任意一個Sentinel都有可能
  • 經過相似投票的方式,其實內部就是經過上面提到的回覆leader_epoch,若是接受者Sentinel回覆的參數是發送者Sentinel的運行ID,就代表當前Sentinel投給了發送者Sentinel這一票,只要有一個Sentinel的票數大於總票的一半以上,那麼那個Sentinel就會成爲領頭Sentinel
  • 若是規定時間沒有選出,那麼在一段時間以後會再次進行選舉,直到選出爲止

6. 故障轉移

在選舉出領頭Sentinel以後,領頭Sentinel將對已下線的主服務器執行故障轉移操做,包含如下步驟:

  1. 在主服務器屬下的從服務器選擇一個,轉換爲主服務器
  2. 讓其餘從服務器改成複製新的主服務器
  3. 將已經下線的服務器設置爲新的主服務器的從服務器,一旦舊服務器上線以後,自動鏈接成爲新服務器的從服務器

從服務器挑選規則:將全部從服務器保存到一個列表,對列表進行過濾:

  1. 刪除列表中下線或斷線的
  2. 最近5秒沒有回覆過領頭Sentinel的info命令的
  3. 刪除與主服務器斷開鏈接過長的
  4. 根據從服務器優先級排序,選擇優先級高的
  5. 優先級相同,按照複製的偏移量大小排序,選出偏移量最大的。偏移量大意味着保存的是最新的數據,
  6. 若是還存在多個,按照運行ID排序,選出運行ID最小的

選出以後發送命令sqlveof no one,而後接着每秒一次發送info命令,分析回覆信息,直到被選中的從服務器的rolemaster,表示成功升級爲主服務器。以後修改其餘從服務器的複製目標,發送命令slaveof ip port(ip是升級後的服務器ip,port是升級後服務器的port)。

當舊服務器從新上線,Sentinel會向它發送slaveof命令,讓他成* 爲新的主服務器的從服務器。

Sentinel案例

sentinel-1 sentinel-2 sentinel-3
port 26379
sentinel monitor host6379 127.0.0.1 6379 2
sentinel down-after-milliseconds host6379 60000
sentinel failover-timeout host6379 180000
sentinel parallel-syncs host6379 1
port 26380
sentinel monitor host6379 127.0.0.1 6379 2
sentinel down-after-milliseconds host6379 60000
sentinel failover-timeout host6379 180000
sentinel parallel-syncs host6379 1
port 26381
sentinel monitor host6379 127.0.0.1 6379 2
sentinel down-after-milliseconds host6379 60000
sentinel failover-timeout host6379 180000
sentinel parallel-syncs host6379 1
  • port:配置哨兵端口

  • sentinel monitor host6379 127.0.0.1 6379 2:指示 Sentinel 去監視一個名爲 mymaster 的主服務器, 這個主服務器的 IP 地址爲 127.0.0.1 , 端口號爲 6379 , 而將這個主服務器判斷爲失效至少須要 2 個 Sentinel 贊成 (只要贊成 Sentinel 的數量不達標,自動故障遷移就不會執行)。

  • down-after-milliseconds :選項指定了 Sentinel 認爲服務器host6379已經斷線所需的毫秒數。若是服務器在給定的毫秒數以內, 沒有返回 Sentinel 發送的 PING 命令的回覆, 或者返回一個錯誤, 那麼 Sentinel 將這個服務器標記爲主觀下線。 只有在足夠數量的 Sentinel 都將一個服務器標記爲主觀下線以後, 服務器纔會被標記爲客觀下線,這時自動故障遷移纔會執行。

    • 服務器對 PING 命令的有效回覆能夠是如下三種回覆的其中一種:

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

    若是服務器返回除以上三種回覆以外的其餘回覆, 又或者在指定時間內沒有回覆 PING 命令, 那麼 Sentinel 認爲服務器返回的回覆無效(non-valid)。

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

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

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

參考鏈接:
http://www.redis.cn/topics/sentinel.html

相關文章
相關標籤/搜索