本文檔翻譯自: http://redis.io/topics/sentinel 。html
Redis 的 Sentinel 系統用於管理多個 Redis 服務器(instance), 該系統執行如下三個任務:git
Redis Sentinel 是一個分佈式系統, 你能夠在一個架構中運行多個 Sentinel 進程(progress), 這些進程使用流言協議(gossip protocols)來接收關於主服務器是否下線的信息, 並使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪一個從服務器做爲新的主服務器。github
雖然 Redis Sentinel 釋出爲一個單獨的可執行文件 redis-sentinel , 但實際上它只是一個運行在特殊模式下的 Redis 服務器, 你能夠在啓動一個普通 Redis 服務器時經過給定 --sentinel 選項來啓動 Redis Sentinel 。redis
Redis Sentinel 目前仍在開發中, 這個文檔的內容可能隨着 Sentinel 實現的修改而變動。算法
Redis Sentinel 兼容 Redis 2.4.16 或以上版本, 推薦使用 Redis 2.8.0 或以上的版本。chrome
目前 Sentinel 系統是 Redis 的 unstable 分支的一部分, 你必須到 Redis 項目的 Github 頁面 克隆一份 unstable 分值, 而後經過編譯來得到 Sentinel 系統。ubuntu
Sentinel 程序能夠在編譯後的 src 文檔中發現, 它是一個命名爲 redis-sentinel 的程序。安全
你也能夠經過下一節介紹的方法, 讓 redis-server 程序運行在 Sentinel 模式之下。服務器
另外, 一個新版本的 Sentinel 已經包含在了 Redis 2.8.0 版本的釋出文件中。網絡
對於 redis-sentinel 程序, 你能夠用如下命令來啓動 Sentinel 系統:
redis-sentinel /path/to/sentinel.conf
對於 redis-server 程序, 你能夠用如下命令來啓動一個運行在 Sentinel 模式下的 Redis 服務器:
redis-server /path/to/sentinel.conf --sentinel
兩種方法均可以啓動一個 Sentinel 實例。
啓動 Sentinel 實例必須指定相應的配置文件, 系統會使用配置文件來保存 Sentinel 的當前狀態, 並在 Sentinel 重啓時經過載入配置文件來進行狀態還原。
若是啓動 Sentinel 時沒有指定相應的配置文件, 或者指定的配置文件不可寫(not writable), 那麼 Sentinel 會拒絕啓動。
Redis 源碼中包含了一個名爲 sentinel.conf 的文件, 這個文件是一個帶有詳細註釋的 Sentinel 配置文件示例。
運行一個 Sentinel 所需的最少配置以下所示:
sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 60000 sentinel failover-timeout mymaster 180000 sentinel parallel-syncs mymaster 1 sentinel monitor resque 192.168.1.3 6380 4 sentinel down-after-milliseconds resque 10000 sentinel failover-timeout resque 180000 sentinel parallel-syncs resque 5
第一行配置指示 Sentinel 去監視一個名爲 mymaster 的主服務器, 這個主服務器的 IP 地址爲 127.0.0.1 , 端口號爲 6379 , 而將這個主服務器判斷爲失效至少須要 2 個 Sentinel 贊成 (只要贊成 Sentinel 的數量不達標,自動故障遷移就不會執行)。
不過要注意, 不管你設置要多少個 Sentinel 贊成才能判斷一個服務器失效, 一個 Sentinel 都須要得到系統中多數(majority) Sentinel 的支持, 才能發起一次自動故障遷移, 並預留一個給定的配置紀元 (configuration Epoch ,一個配置紀元就是一個新主服務器配置的版本號)。
換句話說, 在只有少數(minority) Sentinel 進程正常運做的狀況下, 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 來保證每次只有一個從服務器處於不能處理命令請求的狀態。
本文檔剩餘的內容將對 Sentinel 系統的其餘選項進行介紹, 示例配置文件 sentinel.conf 也對相關的選項進行了完整的註釋。
前面說過, Redis 的 Sentinel 中關於下線(down)有兩個不一樣的概念:
若是一個服務器沒有在 master-down-after-milliseconds 選項所指定的時間內, 對向它發送 PING 命令的 Sentinel 返回一個有效回覆(valid reply), 那麼 Sentinel 就會將這個服務器標記爲主觀下線。
服務器對 PING 命令的有效回覆能夠是如下三種回覆的其中一種:
若是服務器返回除以上三種回覆以外的其餘回覆, 又或者在指定時間內沒有回覆 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 之間能夠互相檢查對方的可用性, 並進行信息交換。
你無須爲運行的每一個 Sentinel 分別設置其餘 Sentinel 的地址, 由於 Sentinel 能夠經過發佈與訂閱功能來自動發現正在監視相同主服務器的其餘 Sentinel , 這一功能是經過向頻道 __sentinel__:hello 發送信息來實現的。
與此相似, 你也沒必要手動列出主服務器屬下的全部從服務器, 由於 Sentinel 能夠經過詢問主服務器來得到全部從服務器的信息。
在默認狀況下, Sentinel 使用 TCP 端口 26379 (普通 Redis 服務器使用的是 6379 )。
Sentinel 接受 Redis 協議格式的命令請求, 因此你可使用 redis-cli 或者任何其餘 Redis 客戶端來與 Sentinel 進行通信。
有兩種方式能夠和 Sentinel 進行通信:
如下列出的是 Sentinel 接受的命令:
客戶端能夠將 Sentinel 看做是一個只提供了訂閱功能的 Redis 服務器: 你不可使用 PUBLISH 命令向這個服務器發送信息, 但你能夠用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令, 經過訂閱給定的頻道來獲取相應的事件提醒。
一個頻道可以接收和這個頻道的名字相同的事件。 好比說, 名爲 +sdown 的頻道就能夠接收全部實例進入主觀下線(SDOWN)狀態的事件。
經過執行 PSUBSCRIBE * 命令能夠接收全部事件信息。
如下列出的是客戶端能夠經過訂閱來得到的頻道和信息的格式: 第一個英文單詞是頻道/事件的名字, 其他的是數據的格式。
注意, 當格式中包含 instance details 字樣時, 表示頻道所返回的信息中包含了如下用於識別目標實例的內容:
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
@ 字符以後的內容用於指定主服務器, 這些內容是可選的, 它們僅在 @ 字符以前的內容指定的實例不是主服務器時使用。
一次故障轉移操做由如下步驟組成:
每當一個 Redis 實例被從新配置(reconfigured) —— 不管是被設置成主服務器、從服務器、又或者被設置成其餘主服務器的從服務器 —— Sentinel 都會向被從新配置的實例發送一個 CONFIG REWRITE 命令, 從而確保這些配置會持久化在硬盤裏。
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 發來的配置更新, 從而避免自身由於保存了過時的配置而對實例進行了沒必要要的從新配置。
Redis Sentinel 嚴重依賴計算機的時間功能: 好比說, 爲了判斷一個實例是否可用, Sentinel 會記錄這個實例最後一次相應 PING命令的時間, 並將這個時間和當前時間進行對比, 從而知道這個實例有多長時間沒有和 Sentinel 進行任何成功通信。
不過, 一旦計算機的時間功能出現故障, 或者計算機很是忙碌, 又或者進程由於某些緣由而被阻塞時, Sentinel 可能也會跟着出現故障。
TILT 模式是一種特殊的保護模式: 當 Sentinel 發現系統有些不對勁時, Sentinel 就會進入 TILT 模式。
由於 Sentinel 的時間中斷器默認每秒執行 10 次, 因此咱們預期時間中斷器的兩次執行之間的間隔爲 100 毫秒左右。 Sentinel 的作法是, 記錄上一次時間中斷器執行時的時間, 並將它和這一次時間中斷器執行的時間進行對比:
當 Sentinel 進入 TILT 模式時, 它仍然會繼續監視全部目標, 可是:
若是 TILT 能夠正常維持 30 秒鐘, 那麼 Sentinel 退出 TILT 模式。
該功能還沒有實現
當 Lua 腳本的運行時間超過指定時限時, Redis 就會返回 -BUSY 錯誤。
當出現這種狀況時, Sentinel 在嘗試執行故障轉移操做以前, 會先向服務器發送一個 SCRIPT KILL 命令, 若是服務器正在執行的是一個只讀腳本的話, 那麼這個腳本就會被殺死, 服務器就會回到正常狀態。
關於 Sentinel 客戶端的實現信息能夠參考 Sentinel 客戶端指引手冊 。