Redis 的 Sentinel 系統用於管理多個 Redis 服務器(instance) 該系統執行如下三個任務:python
前面咱們談到,當一個master被sentinel集羣監控時,須要爲它指定一個參數,這個參數指定了當須要判決master爲不可用,而且進行failover時,所須要的sentinel數量,本文中咱們暫時稱這個參數爲票數redis
不過,當failover主備切換真正被觸發後,failover並不會立刻進行,還須要sentinel中的大多數sentinel受權後才能夠進行failover。
當ODOWN時,failover被觸發。failover一旦被觸發,嘗試去進行failover的sentinel會去得到「大多數」sentinel的受權(若是票數比大多數還要大的時候,則詢問更多的sentinel)
這個區別看起來很微妙,可是很容易理解和使用。例如,集羣中有5個sentinel,票數被設置爲2,當2個sentinel認爲一個master已經不可用了之後,將會觸發failover,可是,進行failover的那個sentinel必須先得到至少3個sentinel的受權才能夠實行failover。
若是票數被設置爲5,要達到ODOWN狀態,必須全部5個sentinel都主觀認爲master爲不可用,要進行failover,那麼得得到全部5個sentinel的受權。算法
爲何要先得到大多數sentinel的承認時才能真正去執行failover呢?shell
當一個sentinel被受權後,它將會得到宕掉的master的一份最新配置版本號,當failover執行結束之後,這個版本號將會被用於最新的配置。由於大多數sentinel都已經知道該版本號已經被要執行failover的sentinel拿走了,因此其餘的sentinel都不能再去使用這個版本號。這意味着,每次failover都會附帶有一個獨一無二的版本號。咱們將會看到這樣作的重要性。緩存
並且,sentinel集羣都遵照一個規則:若是sentinel A推薦sentinel B去執行failover,B會等待一段時間後,自行再次去對同一個master執行failover,這個等待的時間是經過failover-timeout配置項去配置的。從這個規則能夠看出,sentinel集羣中的sentinel不會再同一時刻併發去failover同一個master,第一個進行failover的sentinel若是失敗了,另一個將會在必定時間內進行從新進行failover,以此類推。安全
redis sentinel保證了活躍性:若是大多數sentinel可以互相通訊,最終將會有一個被受權去進行failover.
redis sentinel也保證了安全性:每一個試圖去failover同一個master的sentinel都會獲得一個獨一無二的版本號。服務器
一旦一個sentinel成功地對一個master進行了failover,它將會把關於master的最新配置經過廣播形式通知其它sentinel,其它的sentinel則更新對應master的配置。網絡
一個faiover要想被成功實行,sentinel必須可以向選爲master的slave發送SLAVE OF NO ONE命令,而後可以經過INFO命令看到新master的配置信息。架構
當將一個slave選舉爲master併發送SLAVE OF NO ONE`後,即便其它的slave還沒針對新master從新配置本身,failover也被認爲是成功了的,而後全部sentinels將會發布新的配置信息。併發
新配在集羣中相互傳播的方式,就是爲何咱們須要當一個sentinel進行failover時必須被受權一個版本號的緣由。
每一個sentinel使用發佈/訂閱的方式持續地傳播master的配置版本信息,配置傳播的發佈/訂閱管道是:__sentinel__:hello
由於每個配置都有一個版本號,因此以版本號最大的那個爲標準。
舉個栗子:假設有一個名爲mymaster的地址爲192.168.56.11:6379
。一開始,集羣中全部的sentinel都知道這個地址,因而爲mymaster的配置打上版本號1。一段時候後mymaster死了,有一個sentinel被受權用版本號2對其進行failover。若是failover成功了,假設地址改成了192.168.56.12:6279
,此時配置的版本號爲2,進行failover的sentinel會將新配置廣播給其餘的sentinel,因爲其餘sentinel維護的版本號爲1,發現新配置的版本號爲2時,版本號變大了,說明配置更新了,因而就會採用最新的版本號爲2的配置。
這意味着sentinel集羣保證了第二種活躍性:一個可以互相通訊的sentinel集羣最終會採用版本號最高且相同的配置。
SENTINEL is-master-down-by-addr
命令來詢問對方是否定爲給定的服務器已下線。)從sentinel的角度來看,若是發送了PING心跳後,在master-down-after-milliseconds
時間內沒有收到合法的回覆,就達到了SDOWN的條件。
當sentinel發送PING後,如下回復之一都被認爲是合法的:
PING replied with +PONG.
PING replied with -LOADING error.
PING replied with -MASTERDOWN error.
從SDOWN切換到ODOWN不須要任何一致性算法,只須要一個gossip協議:若是一個sentinel收到了足夠多的sentinel發來消息告訴它某個master已經down掉了,SDOWN狀態就會變成ODOWN狀態。若是以後master可用了,這個狀態就會相應地被清理掉。
正如以前已經解釋過了,真正進行failover須要一個受權的過程,可是全部的failover都開始於一個ODOWN狀態。
ODOWN狀態只適用於master,對於不是master的redis節點sentinel之間不須要任何協商,slaves和sentinel不會有ODOWN狀態。
雖然sentinel集羣中各個sentinel都互相鏈接彼此來檢查對方的可用性以及互相發送消息。可是你不用在任何一個sentinel配置任何其它的sentinel的節點。由於sentinel利用了master的發佈/訂閱機制去自動發現其它也監控了統一master的sentinel節點。
經過向名爲__sentinel__:hello
的管道中發送消息來實現。
一樣,你也不須要在sentinel中配置某個master的全部slave的地址,sentinel會經過詢問master來獲得這些slave的地址的。
__sentinel__:hello
頻道發送一條信息, 信息中包含了 Sentinel 的 IP 地址、端口號和運行 ID (runid)。__sentinel__:hello
頻道, 查找以前未出現過的 sentinel (looking for unknown sentinels)。 當一個 Sentinel 發現一個新的 Sentinel 時, 它會將新的 Sentinel * 添加到一個列表中, 這個列表保存了 Sentinel 已知的, 監視同一個主服務器的全部其餘 Sentinel 。redis sentinel集羣的配置的一致性模型爲最終一致性,集羣中每一個sentinel最終都會採用最高版本的配置。然而,在實際的應用環境中,有三個不一樣的角色會與sentinel打交道:
Redis實例.
Sentinel實例.
客戶端.
爲了考察整個系統的行爲咱們必須同時考慮到這三個角色。
下面有個簡單的例子,有三個主機,每一個主機分別運行一個redis和一個sentinel:
+-------------+ | Sentinel 1 | <--- Client A | Redis 1 (M) | +-------------+ | | +-------------+ | +------------+ | Sentinel 2 |-----+-- / partition / ----| Sentinel 3 | <--- Client B | Redis 2 (S) | | Redis 3 (M)| +-------------+ +------------+
在這個系統中,初始狀態下redis3是master, redis1和redis2是slave。以後redis3所在的主機網絡不可用了,sentinel1和sentinel2啓動了failover並把redis1選舉爲master。
Sentinel集羣的特性保證了sentinel1和sentinel2獲得了關於master的最新配置。可是sentinel3依然持着的是就的配置,由於它與外界隔離了。
當網絡恢復之後,咱們知道sentinel3將會更新它的配置。可是,若是客戶端所鏈接的master被網絡隔離,會發生什麼呢?
客戶端將依然能夠向redis3寫數據,可是當網絡恢復後,redis3就會變成redis的一個slave,那麼,在網絡隔離期間,客戶端向redis3寫的數據將會丟失。
也許你不會但願這個場景發生:
若是你把redis當作緩存來使用,那麼你也許能容忍這部分數據的丟失。
但若是你把redis當作一個存儲系統來使用,你也許就沒法容忍這部分數據的丟失了。
由於redis採用的是異步複製,在這樣的場景下,沒有辦法避免數據的丟失。然而,你能夠經過如下配置來配置redis3和redis1,使得數據不會丟失。
min-slaves-to-write 1 min-slaves-max-lag 10
經過上面的配置,當一個redis是master時,若是它不能向至少一個slave寫數據(上面的min-slaves-to-write指定了slave的數量),它將會拒絕接受客戶端的寫請求。因爲複製是異步的,master沒法向slave寫數據意味着slave要麼斷開鏈接了,要麼不在指定時間內向master發送同步數據的請求了(上面的min-slaves-max-lag指定了這個時間)。
一次故障轉移操做由如下步驟組成:
每當一個 Redis 實例被從新配置(reconfigured) —— 不管是被設置成主服務器、從服務器、又或者被設置成其餘主服務器的從服務器 —— Sentinel 都會向被從新配置的實例發送一個 CONFIG REWRITE 命令, 從而確保這些配置會持久化在硬盤裏。
Sentinel 使用如下規則來選擇新的主服務器:
snetinel的狀態會被持久化地寫入sentinel的配置文件中。每次當收到一個新的配置時,或者新建立一個配置時,配置會被持久化到硬盤中,並帶上配置的版本戳。這意味着,能夠安全的中止和重啓sentinel進程。
角色 | IP | 端口 |
---|---|---|
Master,sentinel1 | 192.168.56.11 | 6379,26379 |
Slave 01,sentinel2 | 192.168.56.12 | 6379,26379 |
Slave 02,sentinel3 | 192.168.56.13 | 6379,26379 |
cat redis_6379.conf protected-mode yes bind 192.168.56.12 port 6379 daemonize yes supervised no pidfile "/var/run/redis_6379.pid" loglevel notice logfile "/data/app/redis/logs/redis_6379.log" databases 16 dbfilename "dump_6379.rdb" dir "/data/db/redis_6379"
配置redis實例
cd /data/app/redis/conf
啓動: /data/app/redis/bin/redis-server redis_6379.conf
檢查是否啓動: /data/app/redis/bin/redis-cli -h 192.168.56.11 -p 6379 ping
配置主從:
/data/app/redis/bin/redis-cli -h 192.168.56.12 -p 6379 /data/app/redis/bin/redis-cli -h 192.168.56.13 -p 6379 >SLAVEOF 192.168.56.11 6379 >CONFIG REWRITE #寫入配置文件
Master確認主從: /home/mdb/redis/src/redis-cli -h 192.168.56.11 -p 6379
role:master connected_slaves:2 slave0:ip=192.168.56.12,port=6379,state=online,offset=239,lag=1 slave1:ip=192.168.56.13,port=6379,state=online,offset=239,lag=1 master_repl_offset:239
sentinel 節點啓動有兩種方式:
redis-sentinel sentinel_6379.conf
redis-server sentinel_6379.conf --sentinel
port 26379 daemonize no bind 192.168.56.11 logfile "/data/app/redis/logs/sentinel_26379.log" dir "/data/db/sentinel_26379" sentinel monitor mymaster 192.168.56.11 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000
接下來咱們將一行一行地解釋上面的配置項:
sentinel monitor mymaster 192.168.56.11 6379 2
這一行表明sentinel監控的master的名字叫作mymaster,地址爲192.168.56.11:6379
,行尾最後的一個2表明什麼意思呢?咱們知道,網絡是不可靠的,有時候一個sentinel會由於網絡堵塞而誤覺得一個master redis已經死掉了,當sentinel集羣式,解決這個問題的方法就變得很簡單,只須要多個sentinel互相溝通來確認某個master是否真的死了,這個2表明,當集羣中有2個sentinel認爲master死了時,才能真正認爲該master已經不可用了。(sentinel集羣中各個sentinel也有互相通訊,經過gossip協議)。
除了第一行配置,咱們發現剩下的配置都有一個統一的格式:
sentinel <option_name> <master_name> <option_value>
接下來咱們根據上面格式中的option_name一個一個來解釋這些配置項:
down-after-milliseconds
sentinel會向master發送心跳PING來確認master是否存活,若是master在「必定時間範圍」內不迴應PONG 或者是回覆了一個錯誤消息,那麼這個sentinel會主觀地(單方面地)認爲這個master已經不可用了(subjectively down, 也簡稱爲SDOWN)。而這個down-after-milliseconds就是用來指定這個「必定時間範圍」的,單位是毫秒。
不過須要注意的是,這個時候sentinel並不會立刻進行failover主備切換,這個sentinel還須要參考sentinel集羣中其餘sentinel的意見,若是超過某個數量的sentinel也主觀地認爲該master死了,那麼這個master就會被客觀地(注意哦,此次不是主觀,是客觀,與剛纔的subjectively down相對,此次是objectively down,簡稱爲ODOWN)認爲已經死了。須要一塊兒作出決定的sentinel數量在上一條配置中進行配置。
parallel-syncs
在發生failover主備切換時,這個選項指定了最多能夠有多少個slave同時對新的master進行同步,這個數字越小,完成failover所需的時間就越長,可是若是這個數字越大,就意味着越多的slave由於replication而不可用。能夠經過將這個值設爲 1 來保證每次只有一個slave處於不能處理命令請求的狀態。
其餘配置項在sentinel.conf中都有很詳細的解釋。
全部的配置均可以在運行時用命令SENTINEL SET command動態修改。
啓動: /data/app/redis/bin/redis-sentinel /data/app/redis/conf/sentinel_26379.conf
cat ../logs/sentinel_26379.log 99344:X 16 Oct 16:20:59.156 # Sentinel ID is f16a463d7387bf71f5ebce0c969d01d5bd802ac4 99344:X 16 Oct 16:20:59.156 # +monitor master mymaster 192.168.56.11 6379 quorum 2 99344:X 16 Oct 16:20:59.156 * +slave slave 192.168.56.12:6379 192.168.56.12 6379 @ mymaster 192.168.56.11 6379 99344:X 16 Oct 16:20:59.157 * +slave slave 192.168.56.13:6379 192.168.56.13 6379 @ mymaster 192.168.56.11 6379 99344:X 16 Oct 16:21:01.087 * +sentinel sentinel eb2582f3d12d8ed7710a94e6555a858047a91d2e 192.168.56.12 26379 @ mymaster 192.168.56.11 6379 99344:X 16 Oct 16:21:01.119 * +sentinel sentinel 2a716b1f6e6e9ab6688a99160e7a6616b913336b 192.168.56.13 26379 @ mymaster 192.168.56.11 6379
當全部節點啓動之後,配置文件發生了變化,sentinel發現了從節點和其他的 sentinel 節點 去掉了默認的故障轉移,複製參數,
port 26379 daemonize no bind 192.168.56.12 logfile "/data/app/redis/logs/sentinel_26379.log" dir "/data/db/sentinel_26379" sentinel myid eb2582f3d12d8ed7710a94e6555a858047a91d2e sentinel monitor mymaster 192.168.56.13 6379 2 sentinel config-epoch mymaster 1 sentinel leader-epoch mymaster 1 # Generated by CONFIG REWRITE sentinel known-slave mymaster 192.168.56.12 6379 sentinel known-slave mymaster 192.168.56.11 6379 sentinel known-sentinel mymaster 192.168.56.11 26379 f16a463d7387bf71f5ebce0c969d01d5bd802ac4 sentinel known-sentinel mymaster 192.168.56.13 26379 2a716b1f6e6e9ab6688a99160e7a6616b913336b sentinel current-epoch 1
/data/app/redis/bin/redis-cli -h 192.168.56.12 -p 26379 192.168.56.12:26379> info master0:name=mymaster,status=ok,address=192.168.56.11:6379,slaves=2,sentinels=3 192.168.56.12:26379> sentinel failover mymaster OK 192.168.56.12:26379> info master0:name=mymaster,status=ok,address=192.168.56.13:6379,slaves=2,sentinels=3
查看 sentinel 日誌:
21808:X 16 Oct 16:24:54.045 # Executing user requested FAILOVER of 'mymaster' 21808:X 16 Oct 16:24:54.045 # +new-epoch 1 21808:X 16 Oct 16:24:54.045 # +try-failover master mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:54.084 # +vote-for-leader eb2582f3d12d8ed7710a94e6555a858047a91d2e 1 21808:X 16 Oct 16:24:54.084 # +elected-leader master mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:54.084 # +failover-state-select-slave master mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:54.137 # +selected-slave slave 192.168.56.13:6379 192.168.56.13 6379 @ mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:54.137 * +failover-state-send-slaveof-noone slave 192.168.56.13:6379 192.168.56.13 6379 @ mymaster 192.168.56.11 63 79 21808:X 16 Oct 16:24:54.214 * +failover-state-wait-promotion slave 192.168.56.13:6379 192.168.56.13 6379 @ mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:55.177 # +promoted-slave slave 192.168.56.13:6379 192.168.56.13 6379 @ mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:55.177 # +failover-state-reconf-slaves master mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:55.243 * +slave-reconf-sent slave 192.168.56.12:6379 192.168.56.12 6379 @ mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:56.215 * +slave-reconf-inprog slave 192.168.56.12:6379 192.168.56.12 6379 @ mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:56.215 * +slave-reconf-done slave 192.168.56.12:6379 192.168.56.12 6379 @ mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:56.317 # +failover-end master mymaster 192.168.56.11 6379 21808:X 16 Oct 16:24:56.317 # +switch-master mymaster 192.168.56.11 6379 192.168.56.13 6379 21808:X 16 Oct 16:24:56.318 * +slave slave 192.168.56.12:6379 192.168.56.12 6379 @ mymaster 192.168.56.13 6379 21808:X 16 Oct 16:24:56.318 * +slave slave 192.168.56.11:6379 192.168.56.11 6379 @ mymaster 192.168.56.13 6379
模擬故障轉移
查看 sentinel 配置文件更新變化和 redis 主節點變化
sentinel monitor mymaster 192.168.56.13 6379 2 sentinel config-epoch mymaster 1 sentinel leader-epoch mymaster 1 # Generated by CONFIG REWRITE sentinel known-slave mymaster 192.168.56.12 6379 sentinel known-slave mymaster 192.168.56.11 6379 sentinel known-sentinel mymaster 192.168.56.11 26379 f16a463d7387bf71f5ebce0c969d01d5bd802ac4 sentinel known-sentinel mymaster 192.168.56.13 26379 2a716b1f6e6e9ab6688a99160e7a6616b913336b sentinel current-epoch 1
注意事項
如下列出的是Sentinel接受的命令:
PING
:返回PONG。SENTINEL master <master name>
:用於查看監控的某個Redis Master信息,包括配置和狀態等。SENTINEL slaves <master name>
:列出給定主服務器的全部從服務器,以及這些從服務器的當前狀態。SENTINEL sentinels <master name>
:查看給定主服務器的Sentinel實例列表及其狀態。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 reset <pattern>
:強制重設全部監控的Master狀態,清除已知的Slave和Sentinel實例信息,從新獲取並生成配置文件。SENTINEL failover <master name>
:強制發起一次某個Master的failover,若是該Master不可訪問的話。SENTINEL ckquorum <master name>
:檢測Sentinel配置是否合理,failover的條件是否可能知足,主要用來檢測你的Sentinel配置是否正常。SENTINEL flushconfig
:強制Sentinel重寫全部配置信息到配置文件。SENTINEL is-master-down-by-addr <ip> <port>
:一個Sentinel能夠經過向另外一個Sentinel發送SENTINEL is-master-down-by-addr命令來詢問對方是否定爲給定的服務器已下線。如下是一些修改sentinel配置的命令:
SENTINEL MONITOR <name> <ip> <port> <quorum>
這個命令告訴sentinel去監聽一個新的masterSENTINEL REMOVE <name>
命令sentinel放棄對某個master的監聽SENTINEL SET <name> <option> <value>
這個命令很像Redis的CONFIG SET命令,用來改變指定master的配置。支持多個增長新的Sentinel實例很是簡單,修改好配置文件,啓動便可,其餘Sentinel會自動發現該實例並加入集羣。若是要批量啓動一批Sentinel節點,最好以30秒的間隔一個一個啓動爲好,這樣能確保整個 Sentinel集羣的大多數可以及時感知到新節點,知足當時可能發生的選舉條件。
移除一個Sentinel實例會相對麻煩一些,由於Sentinel不會忘記已經感知到的Sentinel實例,因此最好按照下列步驟來處理:
中止將要移除的sentinel進程。
給其他的sentinel進程發送SENTINEL RESET *
命令來重置狀態,忘記將要移除的sentinel,每一個進程之間間隔30秒。
確保全部sentinel對於當前存貨的sentinel數量達成一致,能夠經過SENTINEL MASTER <mastername>
命令來觀察,或者查看配置文件。
sentinel永遠會記錄好一個Master的slaves,即便slave已經與組織失聯很久了。這是頗有用的,由於sentinel集羣必須有能力把一個恢復可用的slave進行從新配置。
而且,failover後,失效的master將會被標記爲新master的一個slave,這樣的話,當它變得可用時,就會重新master上覆制數據。
而後,有時候你想要永久地刪除掉一個slave(有可能它曾經是個master),你只須要發送一個SENTINEL RESET master
命令給全部的sentinels,它們將會更新列表裏可以正確地複製master數據的slave。
客戶端能夠向一個sentinel發送訂閱某個頻道的事件的命令,當有特定的事件發生時,sentinel會通知全部訂閱的客戶端。須要注意的是客戶端只能訂閱,不能發佈。
訂閱頻道的名字與事件的名字一致。例如,頻道名爲sdown 將會發布全部與SDOWN相關的消息給訂閱者。
若是想要訂閱全部消息,只需簡單地使用PSUBSCRIBE *
如下是全部你能夠收到的消息的消息格式,若是你訂閱了全部消息的話。第一個單詞是頻道的名字,其它是數據的格式。
注意:如下的instance details的格式是:
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
若是這個redis實例是一個master,那麼@以後的消息就不會顯示。
+reset-master <instance details> -- 當master被重置時. +slave <instance details> -- 當檢測到一個slave並添加進slave列表時. +failover-state-reconf-slaves <instance details> -- Failover狀態變爲reconf-slaves狀態時 +failover-detected <instance details> -- 當failover發生時 +slave-reconf-sent <instance details> -- sentinel發送SLAVEOF命令把它從新配置時 +slave-reconf-inprog <instance details> -- slave被從新配置爲另一個master的slave,但數據複製還未發生時。 +slave-reconf-done <instance details> -- slave被從新配置爲另一個master的slave而且數據複製已經與master同步時。 -dup-sentinel <instance details> -- 刪除指定master上的冗餘sentinel時 (當一個sentinel從新啓動時,可能會發生這個事件). +sentinel <instance details> -- 當master增長了一個sentinel時。 +sdown <instance details> -- 進入SDOWN狀態時; -sdown <instance details> -- 離開SDOWN狀態時。 +odown <instance details> -- 進入ODOWN狀態時。 -odown <instance details> -- 離開ODOWN狀態時。 +new-epoch <instance details> -- 當前配置版本被更新時。 +try-failover <instance details> -- 達到failover條件,正等待其餘sentinel的選舉。 +elected-leader <instance details> -- 被選舉爲去執行failover的時候。 +failover-state-select-slave <instance details> -- 開始要選擇一個slave當選新master時。 no-good-slave <instance details> -- 沒有合適的slave來擔當新master selected-slave <instance details> -- 找到了一個適合的slave來擔當新master failover-state-send-slaveof-noone <instance details> -- 當把選擇爲新master的slave的身份進行切換的時候。 failover-end-for-timeout <instance details> -- failover因爲超時而失敗時。 failover-end <instance details> -- failover成功完成時。 switch-master <master name> <oldip> <oldport> <newip> <newport> -- 當master的地址發生變化時。一般這是客戶端最感興趣的消息了。 +tilt -- 進入Tilt模式。 -tilt -- 退出Tilt模式。
redis sentinel很是依賴系統時間,例如它會使用系統時間來判斷一個PING回覆用了多久的時間。
然而,假如系統時間被修改了,或者是系統十分繁忙,或者是進程堵塞了,sentinel可能會出現運行不正常的狀況。
當系統的穩定性降低時,TILT模式是sentinel能夠進入的一種的保護模式。當進入TILT模式時,sentinel會繼續監控工做,可是它不會有任何其餘動做,它也不會去迴應is-master-down-by-addr這樣的命令了,由於它在TILT模式下,檢測失效節點的能力已經變得讓人不可信任了。
若是系統恢復正常,持續30秒鐘,sentinel就會退出TITL模式。
注意:該功能還未實現。
當一個腳本的運行時間超過配置的運行時間時,sentinel會返回一個-BUSY 錯誤信號。若是這件事發生在觸發一個failover以前,sentinel將會發送一個SCRIPT KILL命令,若是script是隻讀的話,就能成功執行。
對於一個最小集羣,Redis應該是一個Master帶上兩個Slave,而且開啓下列選項:
min-slaves-to-write 1 min-slaves-max-lag 10
這樣能保證寫入Master的同時至少寫入一個Slave,若是出現網絡分區阻隔併發生failover的時候,能夠保證寫入的數據最終一致而不是丟失,寫入老的Master會直接失敗。
Slave能夠適當設置優先級,除了0以外(0表示永遠不提高爲Master),越小的優先級,越有可能被提示爲Master。若是Slave分佈在多個機房,能夠考慮將和Master同一個機房的Slave的優先級設置的更低以提高他被選爲新的Master的可能性。
考慮到可用性和選舉的須要,Sentinel進程至少爲3個,推薦爲5個。若是有網絡分區,應當適當分佈(好比2個在A機房, 2個在B機房,一個在C機房)等。
客戶端從過去直接鏈接Redis ,變成:
先鏈接一個Sentinel實例
使用 SENTINEL get-master-addr-by-name master-name 獲取Redis地址信息。
鏈接返回的Redis地址信息,經過ROLE命令查詢是不是Master。若是是,鏈接進入正常的服務環節。不然應該斷開從新查詢。
(可選)客戶端能夠經過SENTINEL sentinels
當Sentinel發起failover後,切換了新的Master,Sentinel會發送 CLIENT KILL TYPE normal命令給客戶端,客戶端須要主動斷開對老的Master的連接,而後從新查詢新的Master地址,再重複走上面的流程。這樣的方式仍然相對不夠實時,能夠經過Sentinel提供的Pub/Sub來更快地監聽到failover事件,加快重連。
若是須要實現讀寫分離,讀走Slave,那能夠走SENTINEL slaves
其餘
因爲Redis是異步複製,因此Sentinel其實沒法達到強一致性,它承諾的是最終一致性:最後一次failover的Redis Master贏者通吃,其餘Slave的數據將被丟棄,從新重新的Master複製數據。此外還有前面提到的分區帶來的一致性問題。
其次,Sentinel的選舉算法依賴時間,所以要確保全部機器的時間同步,若是發現時間不一致,Sentinel實現了一個TITL模式來保護系統的可用性。
from redis.sentinel import Sentinel sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1) print(sentinel.discover_master('mymaster')) print(sentinel.discover_slaves('mymaster')) master = sentinel.master_for('mymaster', socket_timeout=0.1) master.set('foo', 'bar') slave = sentinel.slave_for('mymaster', socket_timeout=0.1) slave.get('foo') 'bar'