本文檔是一篇草案,其包含的指引將來可能會隨著Sentinel項目的進展而改變。
Redis Sentinel是Redis實例的監(jiān)控解決方案,處理Redis主服務器的自動故障轉移和服務發(fā)現(xiàn)(誰是一組實例中的當前主服務器)。由于Sentinel具有在故障轉移期間重新配置實例,以及提供配置給連接Redis主服務器或者從服務器的客戶端的雙重責任,客戶端需要有對Redis Sentinel的顯式支持。
這篇文檔針對Redis客戶端開發(fā)人員,他們想在其客戶端實現(xiàn)中支持Sentinel,以達到如下目標:
本文檔是一篇草案,其包含的指引將來可能會隨著 Sentinel 項目的進展而改變。
Redis Sentinel 是 Redis 實例的監(jiān)控解決方案,處理 Redis 主服務器的自動故障轉移和服務發(fā)現(xiàn)(誰是一組實例中的當前主服務器)。由于 Sentinel 具有在故障轉移期間重新配置實例,以及提供配置給連接 Redis 主服務器或者從服務器的客戶端的雙重責任,客戶端需要有對 Redis Sentinel 的顯式支持。
這篇文檔針對 Redis 客戶端開發(fā)人員,他們想在其客戶端實現(xiàn)中支持 Sentinel,以達到如下目標:
要想獲得 Redis Sentinel 如何工作的細節(jié),請查看相關文檔(請查看本系列相關文章,譯者注),本文只包含 Redis 客戶端開發(fā)人員需要的信息,期待讀者已經(jīng)比較熟悉 Redis Sentinel 的工作方式。
Redis Sentinel 通過像”stats”或”cache”這樣的名字來識別每個主服務器。每個名字實際上標識了一組實例,由一個主服務器和若干個從服務器組成。
網(wǎng)絡中用于特定目的的 Redis 主服務器的地址,在一些像自動故障轉移,手工觸發(fā)故障轉移(例如,為了提升一個 Redis 實例),或者其他原因引起的這樣的事件后可能會改變。
通常,Redis 客戶端中有一些硬編碼的配置來指定 IP 地址和端口作為網(wǎng)絡中 Redis 主服務器的地址。但是,如果主服務器的地址改變了,就需要手工介入到每個客戶端了。
支持 Sentinel 的 Redis 客戶端可以從使用 Sentinel 的主服務器的名稱自動發(fā)現(xiàn) Redis 的地址。所以支持 Sentinel 的客戶端應該可以從輸入中獲得,而不是硬編碼的 IP 地址和端口:
下面是客戶端為了從 Sentinel 列表和服務名稱獲得主服務器地址而需要遵循的步驟。
客戶端應該迭代 Sentinel 地址列表。應該嘗試使用較短的超時(大約幾百毫秒)來連接到每一個地址的 Sentinel。遇到錯誤或者超時就嘗試下一個 Sentinel 地址。
如果所有的 Sentinel 地址都沒有嘗試成功,就返回一個錯誤給客戶端。
第一個回應客戶端請求的 Sentinel 被置于列表的開頭,這樣在下次重連時,我們會首先嘗試在上一次連接嘗試是可達的 Sentinel,以最小化延遲。
一旦與 Sentinel 的連接建立起來,客戶端應該重新嘗試在 Sentinel 上執(zhí)行下面的命令:
SENTINEL get-master-addr-by-name master-name
這里的 master-name 應該被替換為用戶指定的真實服務名稱。
調用的結果可能是下面兩種回復之一:
如果收到了 ip:port 對,這個地址應該用來連接到 Redis 主服務器。否則,如果收到了一個 null 回復,客戶端應該嘗試列表中的下一個 Sentinel。
一旦客戶端發(fā)現(xiàn)了主服務器實例的地址,就應該嘗試與主服務器的連接,然后調用 ROLE 命令來驗證實例的角色真的是一個主服務器。
如果 ROLE 命令不可用(Redis 2.8.12 引進的),客戶端可以使用 INFO 復制命令來解析角色:輸出中的某一個字段。
如果實例不是期待中的主服務器,客戶端應該等待一小段時間(幾百毫秒)然后再嘗試從第 1 步開始。
一旦服務名稱被解析為主服務器地址,并且與 Redis 主服務器實例的連接已經(jīng)建立,每次需要重新連接時,客戶端應該重新從第 1 步開始使用 Sentinel 來解析地址。例如,下面的情況下需要重新聯(lián)系 Sentinel:
在上面的情況下或者任何客戶端丟失了與 Redis 服務器連接的情況下,客戶端應該再次解析主服務器地址。
從 Redis 2.8.12 開始,當 Redis Sentinel 改變了實例的配置,例如,提升從服務器為主服務器,故障轉移后降級主服務器來復制新的主服務器,或者只是改變一個舊的(stale)從服務器的主服務器地址,會發(fā)送一個 CLIENT KILL 類型的命令給實例,來確保所有的客戶端都與重新配置過的實例斷開。這會強制客戶端再次解析主服務器地址。
如果客戶端要聯(lián)系一個還未更新信息的 Sentinel,通過 ROLE 命令驗證 Redis 實例角色會失敗,允許客戶端發(fā)現(xiàn)聯(lián)系上的 Sentinel 提供了舊的(stale)信息,然后會重試。
注意:一個舊的主服務器返回在線的同時,客戶端聯(lián)系一個舊的 Sentinel 實例是有可能的,所以客戶端可能連接了一個舊的主服務器,然而 ROLE 的輸出也是匹配的。但是,當主服務器恢復回來以后,Sentinel 將會嘗試將其降級為從服務器,觸發(fā)一次新的斷開。這個邏輯也適用于連接到一個舊的從服務器,其會被重新配置來復制一個不同的主服務器。
有時候客戶端有興趣連接到從服務器,例如,為了分離(scale)讀請求。簡單修改一下第 2 步就可以支持連接從服務器。不是調用下面的命令:
SENTINEL get-master-addr-by-name master-name
客戶端應該調用:
SENTINEL slaves master-name
用于檢索從服務器實例的清單。
相應地,客戶端應該使用 ROLE 命令來驗證實例真的是一個從服務器,以防止分離讀請求到主服務器。
對于實現(xiàn)了連接池的客戶端,當單個連接重連時,應該要再次聯(lián)系 Sentinel,如果是主服務器的地址改變了,所有已經(jīng)存在的連接都要關閉并且重新連接到新的地址。
客戶端應該在遇到錯誤時正確的返回信息給用戶,尤其是:
一旦收到 get-master-addr-by-name 的成功回復,客戶端會按照下面的步驟來更新其內部的 Sentinel 節(jié)點的列表:
客戶端不需要更新自己的配置文件來持久化列表。更新內存中表示的 Sentinel 列表的能力對改進可靠性已經(jīng)很有用了。
介紹 Sentinel 的文檔中展示了客戶端可以使用發(fā)布訂閱來連接 Sentinel 以訂閱 Redis 實例的配置變更。
這種機制可以用來加快客戶端的重配置,也就是,客戶端可以監(jiān)聽發(fā)布訂閱,以知道配置變更什么時候發(fā)生,從而運行上文解釋的三步協(xié)議來解析新的 Redis 主服務器(或者從服務器)地址。
但是,通過發(fā)布訂閱收到的變更消息不能代替上面的步驟,因為不能保證客戶端可以收到所有的變更消息。
要獲得額外信息或者討論這個指引的特定方面,請發(fā)消息到 Redis Google Group。