Redis Sentinel 是一個分布式系統(tǒng)冈欢, 你可以在一個架構中運行多個 Sentinel 進程(progress)了牛, 這些進程使用流言協(xié)議(gossip protocols)來接收關于主服務器是否下線的信息石咬, 并使用投票協(xié)議(agreement protocols)來決定是否執(zhí)行自動故障遷移醋拧, 以及選擇哪個從服務器作為新的主服務器笤受。
Redis 的 Sentinel 系統(tǒng)用于管理多個Redis 服務器(instance)大刊, 該系統(tǒng)執(zhí)行以下三個任務:
- 監(jiān)控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常为迈。
- 提醒(Notification): 當被監(jiān)控的某個 Redis 服務器出現(xiàn)問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發(fā)送通知缺菌。
- 自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時葫辐, Sentinel 會開始一次自動故障遷移操作, 它會將失效主服務器的其中一個從服務器升級為新的主服務器伴郁, 并讓失效主服務器的其他從服務器改為復制新的主服務器耿战; 當客戶端試圖連接失效的主服務器時, 集群也會向客戶端返回新主服務器的地址焊傅, 使得集群可以使用新主服務器代替失效服務器剂陡。
Redis Sentinel 是一個分布式系統(tǒng), 你可以在一個架構中運行多個 Sentinel 進程(progress)狐胎, 這些進程使用流言協(xié)議(gossip protocols)來接收關于主服務器是否下線的信息鸭栖, 并使用投票協(xié)議(agreement protocols)來決定是否執(zhí)行自動故障遷移, 以及選擇哪個從服務器作為新的主服務器握巢。
雖然 Redis Sentinel 釋出為一個單獨的可執(zhí)行文件 redis-sentinel 晕鹊, 但實際上它只是一個運行在特殊模式下的 Redis 服務器, 你可以在啟動一個普通 Redis 服務器時通過給定 –sentinel 選項來啟動 Redis Sentinel 。
啟動 Sentinel
對于 redis-server 程序溅话, 你可以用以下命令來啟動一個運行在 Sentinel 模式下的 Redis 服務器:
redis-server /path/to/sentinel.conf --sentinel
啟動 Sentinel 實例必須指定相應的配置文件晓锻, 系統(tǒng)會使用配置文件來保存 Sentinel 的當前狀態(tài), 并在 Sentinel 重啟時通過載入配置文件來進行狀態(tài)還原飞几。
如果啟動 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 去監(jiān)視一個名為 mymaster 的主服務器窟社, 這個主服務器的 IP 地址為 127.0.0.1 , 端口號為 6379 绪钥, 而將這個主服務器判斷為失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數(shù)量不達標灿里,自動故障遷移就不會執(zhí)行)。
不過要注意程腹, 無論你設置要多少個 Sentinel 同意才能判斷一個服務器失效匣吊, 一個 Sentinel 都需要獲得系統(tǒng)中多數(shù)(majority) Sentinel 的支持, 才能發(fā)起一次自動故障遷移寸潦, 并預留一個給定的配置紀元 (configuration Epoch 色鸳,一個配置紀元就是一個新主服務器配置的版本號)。
換句話說见转, 在只有少數(shù)(minority) Sentinel 進程正常運作的情況下命雀, Sentinel 是不能執(zhí)行自動故障遷移的。
各個選項的功能如下:
-
down-after-milliseconds 選項指定了 Sentinel 認為服務器已經(jīng)斷線所需的毫秒數(shù)斩箫。
如果服務器在給定的毫秒數(shù)之內(nèi)吏砂, 沒有返回 Sentinel 發(fā)送的 PING 命令的回復, 或者返回一個錯誤乘客, 那么 Sentinel 將這個服務器標記為主觀下線(subjectively down狐血,簡稱 SDOWN )。
不過只有一個 Sentinel 將服務器標記為主觀下線并不一定會引起服務器的自動故障遷移: 只有在足夠數(shù)量的 Sentinel 都將一個服務器標記為主觀下線之后易核, 服務器才會被標記為客觀下線(objectively down匈织, 簡稱 ODOWN ), 這時自動故障遷移才會執(zhí)行牡直。
將服務器標記為客觀下線所需的 Sentinel 數(shù)量由對主服務器的配置決定缀匕。
-
parallel-syncs 選項指定了在執(zhí)行故障轉(zhuǎn)移時,最多可以有多少個從服務器同時對新的主服務器進行同步井氢, 這個數(shù)字越小弦追, 完成故障轉(zhuǎn)移所需的時間就越長岳链。
如果從服務器被設置為允許使用過期數(shù)據(jù)集(參見對 redis.conf 文件中對 slave-serve-stale-data 選項的說明)花竞, 那么你可能不希望所有從服務器都在同一時間向新的主服務器發(fā)送同步請求, 因為盡管復制過程的絕大部分步驟都不會阻塞從服務器, 但從服務器在載入主服務器發(fā)來的 RDB 文件時约急, 仍然會造成從服務器在一段時間內(nèi)不能處理命令請求: 如果全部從服務器一起對新的主服務器進行同步零远, 那么就可能會造成所有從服務器在短時間內(nèi)全部不可用的情況出現(xiàn)。
你可以通過將這個值設為 1 來保證每次只有一個從服務器處于不能處理命令請求的狀態(tài)厌蔽。
主觀下線和客觀下線
前面說過牵辣, Redis 的 Sentinel 中關于下線(down)有兩個不同的概念:
- 主觀下線(Subjectively Down, 簡稱 SDOWN)指的是單個 Sentinel 實例對服務器做出的下線判斷奴饮。
- 客觀下線(Objectively Down纬向, 簡稱 ODOWN)指的是多個 Sentinel 實例在對同一個服務器做出 SDOWN 判斷, 并且通過 SENTINEL is-master-down-by-addr 命令互相交流之后戴卜, 得出的服務器下線判斷逾条。 (一個 Sentinel 可以通過向另一個 Sentinel 發(fā)送 SENTINEL is-master-down-by-addr 命令來詢問對方是否認為給定的服務器已下線。)
如果一個服務器沒有在 master-down-after-milliseconds 選項所指定的時間內(nèi)投剥, 對向它發(fā)送 PING 命令的 Sentinel 返回一個有效回復(valid reply)师脂, 那么 Sentinel 就會將這個服務器標記為主觀下線。
服務器對 PING 命令的有效回復可以是以下三種回復的其中一種:
- 返回 +PONG 江锨。
- 返回 -LOADING 錯誤吃警。
- 返回 -MASTERDOWN 錯誤。
如果服務器返回除以上三種回復之外的其他回復啄育, 又或者在指定時間內(nèi)沒有回復 PING 命令酌心, 那么 Sentinel 認為服務器返回的回復無效(non-valid)。
注意挑豌, 一個服務器必須在 master-down-after-milliseconds 毫秒內(nèi)谒府, 一直返回無效回復才會被 Sentinel 標記為主觀下線。
舉個例子浮毯, 如果 master-down-after-milliseconds 選項的值為 30000 毫秒(30 秒)完疫, 那么只要服務器能在每 29 秒之內(nèi)返回至少一次有效回復, 這個服務器就仍然會被認為是處于正常狀態(tài)的债蓝。
從主觀下線狀態(tài)切換到客觀下線狀態(tài)并沒有使用嚴格的法定人數(shù)算法(strong quorum algorithm)壳鹤, 而是使用了流言協(xié)議: 如果 Sentinel 在給定的時間范圍內(nèi), 從其他 Sentinel 那里接收到了足夠數(shù)量的主服務器下線報告饰迹, 那么 Sentinel 就會將主服務器的狀態(tài)從主觀下線改變?yōu)榭陀^下線芳誓。 如果之后其他 Sentinel 不再報告主服務器已下線, 那么客觀下線狀態(tài)就會被移除啊鸭。
客觀下線條件只適用于主服務器: 對于任何其他類型的 Redis 實例锹淌, Sentinel 在將它們判斷為下線前不需要進行協(xié)商, 所以從服務器或者其他 Sentinel 永遠不會達到客觀下線條件赠制。
只要一個 Sentinel 發(fā)現(xiàn)某個主服務器進入了客觀下線狀態(tài)赂摆, 這個 Sentinel 就可能會被其他 Sentinel 推選出, 并對失效的主服務器執(zhí)行自動故障遷移操作。
每個 Sentinel 都需要定期執(zhí)行的任務
- 每個 Sentinel 以每秒鐘一次的頻率向它所知的主服務器烟号、從服務器以及其他 Sentinel 實例發(fā)送一個 PING 命令绊谭。
- 如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 那么這個實例會被 Sentinel 標記為主觀下線汪拥。 一個有效回復可以是: +PONG 达传、 -LOADING 或者 -MASTERDOWN 。
- 如果一個主服務器被標記為主觀下線迫筑, 那么正在監(jiān)視這個主服務器的所有 Sentinel 要以每秒一次的頻率確認主服務器的確進入了主觀下線狀態(tài)宪赶。
- 如果一個主服務器被標記為主觀下線, 并且有足夠數(shù)量的 Sentinel (至少要達到配置文件指定的數(shù)量)在指定的時間范圍內(nèi)同意這一判斷脯燃, 那么這個主服務器被標記為客觀下線逊朽。
- 在一般情況下, 每個 Sentinel 會以每 10 秒一次的頻率向它已知的所有主服務器和從服務器發(fā)送 INFO 命令曲伊。 當一個主服務器被 Sentinel 標記為客觀下線時叽讳, Sentinel 向下線主服務器的所有從服務器發(fā)送 INFO 命令的頻率會從 10 秒一次改為每秒一次。
- 當沒有足夠數(shù)量的 Sentinel 同意主服務器已經(jīng)下線坟募, 主服務器的客觀下線狀態(tài)就會被移除岛蚤。 當主服務器重新向 Sentinel 的 PING 命令返回有效回復時, 主服務器的主管下線狀態(tài)就會被移除懈糯。
自動發(fā)現(xiàn) Sentinel 和從服務器
一個 Sentinel 可以與其他多個 Sentinel 進行連接涤妒,各個 Sentinel 之間可以互相檢查對方的可用性,并進行信息交換赚哗。
你無須為運行的每個 Sentinel 分別設置其他 Sentinel 的地址她紫, 因為 Sentinel 可以通過發(fā)布與訂閱功能來自動發(fā)現(xiàn)正在監(jiān)視相同主服務器的其他 Sentinel , 這一功能是通過向頻道 sentinel:hello 發(fā)送信息來實現(xiàn)的屿储。
與此類似贿讹, 你也不必手動列出主服務器屬下的所有從服務器, 因為 Sentinel 可以通過詢問主服務器來獲得所有從服務器的信息够掠。
- 每個 Sentinel 會以每兩秒一次的頻率民褂, 通過發(fā)布與訂閱功能, 向被它監(jiān)視的所有主服務器和從服務器的 sentinel:hello 頻道發(fā)送一條信息疯潭, 信息中包含了 Sentinel 的 IP 地址赊堪、端口號和運行 ID (runid)。
- 每個 Sentinel 都訂閱了被它監(jiān)視的所有主服務器和從服務器的 sentinel:hello 頻道竖哩, 查找之前未出現(xiàn)過的 sentinel (looking for unknown sentinels)哭廉。 當一個 Sentinel 發(fā)現(xiàn)一個新的 Sentinel 時, 它會將新的 Sentinel 添加到一個列表中相叁, 這個列表保存了 Sentinel 已知的遵绰, 監(jiān)視同一個主服務器的所有其他 Sentinel 辽幌。
- Sentinel 發(fā)送的信息中還包括完整的主服務器當前配置(configuration)。 如果一個 Sentinel 包含的主服務器配置比另一個 Sentinel 發(fā)送的配置要舊街立, 那么這個 Sentinel 會立即升級到新配置上舶衬。
- 在將一個新 Sentinel 添加到監(jiān)視主服務器的列表上面之前埠通, Sentinel 會先檢查列表中是否已經(jīng)包含了和要添加的 Sentinel 擁有相同運行 ID 或者相同地址(包括 IP 地址和端口號)的 Sentinel 赎离, 如果是的話, Sentinel 會先移除列表中已有的那些擁有相同運行 ID 或者相同地址的 Sentinel 端辱, 然后再添加新 Sentinel 梁剔。
故障轉(zhuǎn)移
每當一個 Redis 實例被重新配置(reconfigured) —— 無論是被設置成主服務器、從服務器舞蔽、又或者被設置成其他主服務器的從服務器 —— Sentinel 都會向被重新配置的實例發(fā)送一個 CONFIG REWRITE 命令荣病, 從而確保這些配置會持久化在硬盤里。
Sentinel 使用以下規(guī)則來選擇新的主服務器:
- 在失效主服務器屬下的從服務器當中渗柿, 那些被標記為主觀下線个盆、已斷線、或者最后一次回復 PING 命令的時間大于五秒鐘的從服務器都會被淘汰朵栖。
- 在失效主服務器屬下的從服務器當中颊亮, 那些與失效主服務器連接斷開的時長超過 down-after 選項指定的時長十倍的從服務器都會被淘汰。
- 在經(jīng)歷了以上兩輪淘汰之后剩下來的從服務器中陨溅, 我們選出復制偏移量(replication offset)最大的那個從服務器作為新的主服務器终惑; 如果復制偏移量不可用, 或者從服務器的復制偏移量相同门扇, 那么帶有最小運行 ID 的那個從服務器成為新的主服務器雹有。
Sentinel 狀態(tài)的持久化
Sentinel 的狀態(tài)會被持久化在 Sentinel 配置文件里面。
每當 Sentinel 接收到一個新的配置臼寄, 或者當領頭 Sentinel 為主服務器創(chuàng)建一個新的配置時霸奕, 這個配置會與配置紀元一起被保存到磁盤里面。
這意味著停止和重啟 Sentinel 進程都是安全的吉拳。