# Sentinel
Note
本文檔翻譯自: [http://redis.io/topics/sentinel](http://redis.io/topics/sentinel) 。
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 。
Warning
Redis Sentinel 目前仍在開發中, 這個文檔的內容可能隨著 Sentinel 實現的修改而變更。
Redis Sentinel 兼容 Redis 2.4.16 或以上版本, 推薦使用 Redis 2.8.0 或以上的版本。
## 獲取 Sentinel
目前 Sentinel 系統是 Redis 的 `unstable` 分支的一部分, 你必須到 [Redis 項目的 Github 頁面](https://github.com/antirez/redis) 克隆一份 `unstable` 分值, 然后通過編譯來獲得 Sentinel 系統。
Sentinel 程序可以在編譯后的 `src` 文檔中發現, 它是一個命名為 `redis-sentinel` 的程序。
你也可以通過下一節介紹的方法, 讓 `redis-server` 程序運行在 Sentinel 模式之下。
另外, 一個新版本的 Sentinel 已經包含在了 Redis 2.8.0 版本的釋出文件中。
## 啟動 Sentinel
對于 `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 會拒絕啟動。
## 配置 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](../connection/ping.html#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)有兩個不同的概念:
* 主觀下線(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](../connection/ping.html#ping) 命令的 Sentinel 返回一個有效回復(valid reply), 那么 Sentinel 就會將這個服務器標記為主觀下線。
服務器對 [PING](../connection/ping.html#ping) 命令的有效回復可以是以下三種回復的其中一種:
* 返回 `+PONG` 。
* 返回 `-LOADING` 錯誤。
* 返回 `-MASTERDOWN` 錯誤。
如果服務器返回除以上三種回復之外的其他回復, 又或者在指定時間內沒有回復 [PING](../connection/ping.html#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](../connection/ping.html#ping) 命令。
* 如果一個實例(instance)距離最后一次有效回復 [PING](../connection/ping.html#ping) 命令的時間超過 `down-after-milliseconds` 選項所指定的值, 那么這個實例會被 Sentinel 標記為主觀下線。 一個有效回復可以是: `+PONG` 、 `-LOADING` 或者 `-MASTERDOWN` 。
* 如果一個主服務器被標記為主觀下線, 那么正在監視這個主服務器的所有 Sentinel 要以每秒一次的頻率確認主服務器的確進入了主觀下線狀態。
* 如果一個主服務器被標記為主觀下線, 并且有足夠數量的 Sentinel (至少要達到配置文件指定的數量)在指定的時間范圍內同意這一判斷, 那么這個主服務器被標記為客觀下線。
* 在一般情況下, 每個 Sentinel 會以每 10 秒一次的頻率向它已知的所有主服務器和從服務器發送 [INFO](../server/info.html#info) 命令。 當一個主服務器被 Sentinel 標記為客觀下線時, Sentinel 向下線主服務器的所有從服務器發送 [INFO](../server/info.html#info) 命令的頻率會從 10 秒一次改為每秒一次。
* 當沒有足夠數量的 Sentinel 同意主服務器已經下線, 主服務器的客觀下線狀態就會被移除。 當主服務器重新向 Sentinel 的 [PING](../connection/ping.html#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 。
## Sentinel API
在默認情況下, Sentinel 使用 TCP 端口 `26379` (普通 Redis 服務器使用的是 `6379` )。
Sentinel 接受 Redis 協議格式的命令請求, 所以你可以使用 `redis-cli` 或者任何其他 Redis 客戶端來與 Sentinel 進行通訊。
有兩種方式可以和 Sentinel 進行通訊:
* 第一種方法是通過直接發送命令來查詢被監視 Redis 服務器的當前狀態, 以及 Sentinel 所知道的關于其他 Sentinel 的信息, 諸如此類。
* 另一種方法是使用發布與訂閱功能, 通過接收 Sentinel 發送的通知: 當執行故障轉移操作, 或者某個被監視的服務器被判斷為主觀下線或者客觀下線時, Sentinel 就會發送相應的信息。
### Sentinel 命令
以下列出的是 Sentinel 接受的命令:
* [PING](../connection/ping.html#ping) :返回 `PONG` 。
* `SENTINEL masters` :列出所有被監視的主服務器,以及這些主服務器的當前狀態。
* `SENTINEL slaves <master name>` :列出給定主服務器的所有從服務器,以及這些從服務器的當前狀態。
* `SENTINEL get-master-addr-by-name <master name>` : 返回給定名字的主服務器的 IP 地址和端口號。 如果這個主服務器正在執行故障轉移操作, 或者針對這個主服務器的故障轉移操作已經完成, 那么這個命令返回新的主服務器的 IP 地址和端口號。
* `SENTINEL reset <pattern>` : 重置所有名字和給定模式 `pattern` 相匹配的主服務器。 `pattern` 參數是一個 Glob 風格的模式。 重置操作清除主服務器目前的所有狀態, 包括正在執行中的故障轉移, 并移除目前已經發現和關聯的, 主服務器的所有從服務器和 Sentinel 。
* `SENTINEL failover <master name>` : 當主服務器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移 (不過發起故障轉移的 Sentinel 會向其他 Sentinel 發送一個新的配置,其他 Sentinel 會根據這個配置進行相應的更新)。
### 發布與訂閱信息
客戶端可以將 Sentinel 看作是一個只提供了訂閱功能的 Redis 服務器: 你不可以使用 [PUBLISH](../pub_sub/publish.html#publish) 命令向這個服務器發送信息, 但你可以用 [SUBSCRIBE](../pub_sub/subscribe.html#subscribe) 命令或者 [PSUBSCRIBE](../pub_sub/psubscribe.html#psubscribe) 命令, 通過訂閱給定的頻道來獲取相應的事件提醒。
一個頻道能夠接收和這個頻道的名字相同的事件。 比如說, 名為 `+sdown` 的頻道就可以接收所有實例進入主觀下線(SDOWN)狀態的事件。
通過執行 `PSUBSCRIBE *` 命令可以接收所有事件信息。
以下列出的是客戶端可以通過訂閱來獲得的頻道和信息的格式: 第一個英文單詞是頻道/事件的名字, 其余的是數據的格式。
注意, 當格式中包含 `instance details` 字樣時, 表示頻道所返回的信息中包含了以下用于識別目標實例的內容:
```
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
```
`@` 字符之后的內容用于指定主服務器, 這些內容是可選的, 它們僅在 `@` 字符之前的內容指定的實例不是主服務器時使用。
* `+reset-master <instance details>` :主服務器已被重置。
* `+slave <instance details>` :一個新的從服務器已經被 Sentinel 識別并關聯。
* `+failover-state-reconf-slaves <instance details>` :故障轉移狀態切換到了 `reconf-slaves` 狀態。
* `+failover-detected <instance details>` :另一個 Sentinel 開始了一次故障轉移操作,或者一個從服務器轉換成了主服務器。
* `+slave-reconf-sent <instance details>` :領頭(leader)的 Sentinel 向實例發送了 [SLAVEOF](../server/slaveof.html#slaveof) 命令,為實例設置新的主服務器。
* `+slave-reconf-inprog <instance details>` :實例正在將自己設置為指定主服務器的從服務器,但相應的同步過程仍未完成。
* `+slave-reconf-done <instance details>` :從服務器已經成功完成對新主服務器的同步。
* `-dup-sentinel <instance details>` :對給定主服務器進行監視的一個或多個 Sentinel 已經因為重復出現而被移除 —— 當 Sentinel 實例重啟的時候,就會出現這種情況。
* `+sentinel <instance details>` :一個監視給定主服務器的新 Sentinel 已經被識別并添加。
* `+sdown <instance details>` :給定的實例現在處于主觀下線狀態。
* `-sdown <instance details>` :給定的實例已經不再處于主觀下線狀態。
* `+odown <instance details>` :給定的實例現在處于客觀下線狀態。
* `-odown <instance details>` :給定的實例已經不再處于客觀下線狀態。
* `+new-epoch <instance details>` :當前的紀元(epoch)已經被更新。
* `+try-failover <instance details>` :一個新的故障遷移操作正在執行中,等待被大多數 Sentinel 選中(waiting to be elected by the majority)。
* `+elected-leader <instance details>` :贏得指定紀元的選舉,可以進行故障遷移操作了。
* `+failover-state-select-slave <instance details>` :故障轉移操作現在處于 `select-slave` 狀態 —— Sentinel 正在尋找可以升級為主服務器的從服務器。
* `no-good-slave <instance details>` :Sentinel 操作未能找到適合進行升級的從服務器。Sentinel 會在一段時間之后再次嘗試尋找合適的從服務器來進行升級,又或者直接放棄執行故障轉移操作。
* `selected-slave <instance details>` :Sentinel 順利找到適合進行升級的從服務器。
* `failover-state-send-slaveof-noone <instance details>` :Sentinel 正在將指定的從服務器升級為主服務器,等待升級功能完成。
* `failover-end-for-timeout <instance details>` :故障轉移因為超時而中止,不過最終所有從服務器都會開始復制新的主服務器(slaves will eventually be configured to replicate with the new master anyway)。
* `failover-end <instance details>` :故障轉移操作順利完成。所有從服務器都開始復制新的主服務器了。
* `+switch-master <master name> <oldip> <oldport> <newip> <newport>` :配置變更,主服務器的 IP 和地址已經改變。 **這是絕大多數外部用戶都關心的信息。**
* `+tilt` :進入 tilt 模式。
* `-tilt` :退出 tilt 模式。
## 故障轉移
一次故障轉移操作由以下步驟組成:
* 發現主服務器已經進入客觀下線狀態。
* 對我們的當前紀元進行自增(詳情請參考 [Raft leader election](https://www.google.com.hk/search?q=Raft+leader+election&client=ubuntu&a…aft+leader+election&aqs=chrome..69i57&sourceid=chrome&ie=UTF-8) ), 并嘗試在這個紀元中當選。
* 如果當選失敗, 那么在設定的故障遷移超時時間的兩倍之后, 重新嘗試當選。 如果當選成功, 那么執行以下步驟。
* 選出一個從服務器,并將它升級為主服務器。
* 向被選中的從服務器發送 `SLAVEOF NO ONE` 命令,讓它轉變為主服務器。
* 通過發布與訂閱功能, 將更新后的配置傳播給所有其他 Sentinel , 其他 Sentinel 對它們自己的配置進行更新。
* 向已下線主服務器的從服務器發送 [SLAVEOF](../server/slaveof.html#slaveof) 命令, 讓它們去復制新的主服務器。
* 當所有從服務器都已經開始復制新的主服務器時, 領頭 Sentinel 終止這次故障遷移操作。
Note
每當一個 Redis 實例被重新配置(reconfigured) —— 無論是被設置成主服務器、從服務器、又或者被設置成其他主服務器的從服務器 —— Sentinel 都會向被重新配置的實例發送一個 `CONFIG REWRITE` 命令, 從而確保這些配置會持久化在硬盤里。
Sentinel 使用以下規則來選擇新的主服務器:
* 在失效主服務器屬下的從服務器當中, 那些被標記為主觀下線、已斷線、或者最后一次回復 [PING](../connection/ping.html#ping) 命令的時間大于五秒鐘的從服務器都會被淘汰。
* 在失效主服務器屬下的從服務器當中, 那些與失效主服務器連接斷開的時長超過 `down-after` 選項指定的時長十倍的從服務器都會被淘汰。
* 在經歷了以上兩輪淘汰之后剩下來的從服務器中, 我們選出復制偏移量(replication offset)最大的那個從服務器作為新的主服務器; 如果復制偏移量不可用, 或者從服務器的復制偏移量相同, 那么帶有最小運行 ID 的那個從服務器成為新的主服務器。
### Sentinel 自動故障遷移的一致性特質
Sentinel 自動故障遷移使用 Raft 算法來選舉領頭(leader) Sentinel , 從而確保在一個給定的紀元(epoch)里, 只有一個領頭產生。
這表示在同一個紀元中, 不會有兩個 Sentinel 同時被選中為領頭, 并且各個 Sentinel 在同一個紀元中只會對一個領頭進行投票。
更高的配置紀元總是優于較低的紀元, 因此每個 Sentinel 都會主動使用更新的紀元來代替自己的配置。
簡單來說, 我們可以將 Sentinel 配置看作是一個帶有版本號的狀態。 一個狀態會以最后寫入者勝出(last-write-wins)的方式(也即是,最新的配置總是勝出)傳播至所有其他 Sentinel 。
舉個例子, 當出現網絡分割([network partitions](http://en.wikipedia.org/wiki/Network_partition))時, 一個 Sentinel 可能會包含了較舊的配置, 而當這個 Sentinel 接到其他 Sentinel 發來的版本更新的配置時, Sentinel 就會對自己的配置進行更新。
如果要在網絡分割出現的情況下仍然保持一致性, 那么應該使用 `min-slaves-to-write` 選項, 讓主服務器在連接的從實例少于給定數量時停止執行寫操作, 與此同時, 應該在每個運行 Redis 主服務器或從服務器的機器上運行 Redis Sentinel 進程。
### Sentinel 狀態的持久化
Sentinel 的狀態會被持久化在 Sentinel 配置文件里面。
每當 Sentinel 接收到一個新的配置, 或者當領頭 Sentinel 為主服務器創建一個新的配置時, 這個配置會與配置紀元一起被保存到磁盤里面。
這意味著停止和重啟 Sentinel 進程都是安全的。
### Sentinel 在非故障遷移的情況下對實例進行重新配置
即使沒有自動故障遷移操作在進行, Sentinel 總會嘗試將當前的配置設置到被監視的實例上面。 特別是:
* 根據當前的配置, 如果一個從服務器被宣告為主服務器, 那么它會代替原有的主服務器, 成為新的主服務器, 并且成為原有主服務器的所有從服務器的復制對象。
* 那些連接了錯誤主服務器的從服務器會被重新配置, 使得這些從服務器會去復制正確的主服務器。
不過, 在以上這些條件滿足之后, Sentinel 在對實例進行重新配置之前仍然會等待一段足夠長的時間, 確保可以接收到其他 Sentinel 發來的配置更新, 從而避免自身因為保存了過期的配置而對實例進行了不必要的重新配置。
## TILT 模式
Redis Sentinel 嚴重依賴計算機的時間功能: 比如說, 為了判斷一個實例是否可用, Sentinel 會記錄這個實例最后一次相應 [PING](../connection/ping.html#ping) 命令的時間, 并將這個時間和當前時間進行對比, 從而知道這個實例有多長時間沒有和 Sentinel 進行任何成功通訊。
不過, 一旦計算機的時間功能出現故障, 或者計算機非常忙碌, 又或者進程因為某些原因而被阻塞時, Sentinel 可能也會跟著出現故障。
TILT 模式是一種特殊的保護模式: 當 Sentinel 發現系統有些不對勁時, Sentinel 就會進入 TILT 模式。
因為 Sentinel 的時間中斷器默認每秒執行 10 次, 所以我們預期時間中斷器的兩次執行之間的間隔為 100 毫秒左右。 Sentinel 的做法是, 記錄上一次時間中斷器執行時的時間, 并將它和這一次時間中斷器執行的時間進行對比:
* 如果兩次調用時間之間的差距為負值, 或者非常大(超過 2 秒鐘), 那么 Sentinel 進入 TILT 模式。
* 如果 Sentinel 已經進入 TILT 模式, 那么 Sentinel 延遲退出 TILT 模式的時間。
當 Sentinel 進入 TILT 模式時, 它仍然會繼續監視所有目標, 但是:
* 它不再執行任何操作,比如故障轉移。
* 當有實例向這個 Sentinel 發送 `SENTINEL is-master-down-by-addr` 命令時, Sentinel 返回負值: 因為這個 Sentinel 所進行的下線判斷已經不再準確。
如果 TILT 可以正常維持 30 秒鐘, 那么 Sentinel 退出 TILT 模式。
## 處理 `-BUSY` 狀態
Warning
該功能尚未實現
當 Lua 腳本的運行時間超過指定時限時, Redis 就會返回 `-BUSY` 錯誤。
當出現這種情況時, Sentinel 在嘗試執行故障轉移操作之前, 會先向服務器發送一個 [SCRIPT KILL](../script/script_kill.html#script-kill) 命令, 如果服務器正在執行的是一個只讀腳本的話, 那么這個腳本就會被殺死, 服務器就會回到正常狀態。
## Sentinel 的客戶端實現
關于 Sentinel 客戶端的實現信息可以參考 [Sentinel 客戶端指引手冊](http://redis.io/topics/sentinel-clients) 。
- Redis 文檔
- 鍵空間通知(keyspace notification)
- 事務(transaction)
- 發布與訂閱(pub/sub)
- 復制(Replication)
- 通信協議(protocol)
- 持久化(persistence)
- Sentinel
- 集群教程
- Redis 集群規范
- Redis 命令參考
- Key(鍵)
- DEL
- DUMP
- EXISTS
- EXPIRE
- EXPIREAT
- KEYS
- MIGRATE
- MOVE
- OBJECT
- PERSIST
- PEXPIRE
- PEXPIREAT
- PTTL
- RANDOMKEY
- RENAME
- RENAMENX
- RESTORE
- SORT
- TYPE
- SCAN
- String(字符串)
- APPEND
- BITCOUNT
- BITOP
- DECR
- DECRBY
- GET
- GETBIT
- GETRANGE
- GETSET
- INCR
- INCRBY
- INCRBYFLOAT
- MGET
- MSET
- MSETNX
- PSETEX
- SET
- SETBIT
- SETEX
- SETNX
- SETRANGE
- STRLEN
- Hash(哈希表)
- HDEL
- HEXISTS
- HGET
- HGETALL
- HINCRBY
- HINCRBYFLOAT
- HKEYS
- HLEN
- HMGET
- HMSET
- HSET
- HSETNX
- HVALS
- HSCAN
- List(列表)
- BLPOP
- BRPOP
- BRPOPLPUSH
- LINDEX
- LINSERT
- LLEN
- LPOP
- LPUSH
- LRANGE
- LREM
- LSET
- LTRIM
- RPOP
- RPOPLPUSH
- RPUSH
- RPUSHX
- Set(集合)
- SADD
- SCARD
- SDIFF
- SDIFFSTORE
- SINTER
- SINTER
- SINTERSTORE
- SISMEMBER
- SMEMBERS
- SMOVE
- SPOP
- SRANDMEMBER
- SREM
- SUNION
- SUNIONSTORE
- SSCAN
- SortedSet(有序集合)
- ZADD
- ZCARD
- ZCOUNT
- ZINCRBY
- ZRANGE
- ZRANGEBYSCORE
- ZRANK
- ZREM
- ZREMRANGEBYRANK
- ZREMRANGEBYSCORE
- ZREVRANGE
- ZREVRANGEBYSCORE
- ZREVRANK
- ZSCORE
- ZUNIONSTORE
- ZINTERSTORE
- ZSCAN
- Pub/Sub(發布/訂閱)
- PSUBSCRIBE
- PUBLISH
- PUBSUB
- PUNSUBSCRIBE
- SUBSCRIBE
- UNSUBSCRIBE
- Transaction(事務)
- DISCARD
- EXEC
- MULTI
- UNWATCH
- WATCH
- Script(腳本)
- EVAL
- EVALSHA
- SCRIPT EXISTS
- SCRIPT FLUSH
- SCRIPT KILL
- SCRIPT LOAD
- Connection(連接)
- AUTH
- ECHO
- PING
- QUIT
- SELECT
- Server(服務器)
- BGREWRITEAOF
- BGSAVE
- CLIENT GETNAME
- CLIENT KILL
- CLIENT LIST
- CLIENT SETNAME
- CONFIG GET
- CONFIG RESETSTAT
- CONFIG REWRITE
- CONFIG SET
- DBSIZE
- DEBUG OBJECT
- DEBUG SEGFAULT
- FLUSHALL
- FLUSHDB
- INFO
- LASTSAVE
- MONITOR
- PSYNC
- SAVE
- SHUTDOWN
- SLAVEOF
- SLOWLOG
- SYNC
- TIME
- 關于