Redis Sentinel Test

Redis Sentinel 是一套用於管理Redis實例的分佈式系統,主要完成3項任務:

1. Monitoring:持續監控Redis master或slave實例的運行情況是否符合預期
2. Notification:若被監控的Redis實例運行異常,sentinel會通過API通知外界(人或程序)
3. Automation failover:若master實例故障,sentinel會重新選主並啓動自動故障切換:選擇slave-priority最小的那個slave實例 並將其提升爲master,同時修改其它slave的配置,使其master配置項指向新的master,當old master恢復重啓後,會自動降級爲new master的slave.最後,根據配置,Redis Sentinel還會將新的master地址通知給當前正在訪問Redis的應用程序.

Raft分佈式算法

1. 主要用途:用於分佈式系統,系統容錯,以及選出領頭羊
2. 作者:Diego Ongaro,畢業於哈佛
3. 目前用到這個算法的項目有:
a. CoreOS
b. ectd : a distributed, consistent shared configuration
c. LogCabin : 分佈式存儲系統
d. redis sentinel : redis 的監控系統

Sentinel使用的Raft算法核心: 原則

1. 所有sentinel都有選舉的領頭羊的權利
2. 每個sentinel都會要求其他sentinel選舉自己爲領頭羊(主要由發現redis客觀下線的sentinel先發起選舉)
3. 每個sentinel只有一次選舉的機會
4. 採用先到先得的原則
5. 一旦加入到系統了,則不會自動清除(這一點很重要, why?)
6. 每個sentinel都有唯一的uid,不會因爲重啓而變更
7. 達到領頭羊的條件是 N/2 + 1個sentinel選擇了自己
8. 採用配置紀元,如果一次選舉出現腦裂,則配置紀元會遞增,進入下一次選舉,所有sentinel都會處於統一配置紀元,以最新的爲標準.

Sentinel 配置樣例

   port 26379
  dir /tmp
  sentinel monitor mymaster 127.0.0.1 6379 2
  sentinel down-after-milliseconds mymaster 30000
  sentinel parallel-syncs mymaster 1
  sentinel failover-timeout mymaster 180000
  sentinel notification-script myredis <script-path>

其中:
port: 指定sentinel的偵聽端口(即與redis server或client建立tcp連接的端口)
dir: 工作路徑,sentinel一般指定/tmp比較簡單
monitor: 指定sentinel要monitor的redis實例,包括一個redis實例的別名(alias)及redis實例的ip+port,該行最後的數字 2表示至少2個setinel實例同時檢測到redis server異常時,纔將redis server的狀態判決爲real fail.也即,若這裏配置爲2,但實際部署中sentinel只部署了1套,則即使redis實例已經掛掉,sentinel也不會給出任何警告.這一 點需要特別引起注意.
down-after-milliseconds: 指定sentinel監控到redis實例持續異常多長時間後,會判決其狀態爲down.若實際業務需要sentinel儘快判決出redis實例異常,則該值可適當配小.
failover-timeout: 若sentinel在該配置值內未能完成failover操作(即故障時master/slave自動切換),則認爲本次failover失敗.該配置有 4個用途,具體可參考sentinel.conf中的說明,限於篇幅,此處不再贅述.
parallel-syncs: 指定failover過程中,同時被sentinel reconfigure的最大slave實例數.由於reconfigure過程中,對應的slave會中斷響應客戶端請求,故爲避免所有的slave同時不可用,該值需適當配小.
notification-script: 指定sentinel檢測到master-name指向的實例異常時,調用的報警腳本.該配置項可選,但線上系統建議配置.

啓動 sentinel的方法

當前Redis stable版已經自帶了redis-sentinel這個工具.雖然 Redis Sentinel 已經提供了一個單獨的可執行文件 redis-sentinel , 但實際上它只是一個運行在特殊模式下的 Redis實例, 你可以在啓動一個普通 Redis實例時通過給定 –sentinel 選項來啓動 Redis Sentinel 實例.也就是說:
redis-sentinel /path/to/sentinel.conf
等同於
redis-server /path/to/sentinel.conf –sentinel
其中sentinel.conf是redis的配置文件,Redis sentinel會需要寫入配置文件來保存sentinel的當前狀態.當配置文件無法寫入時,Sentinel啓動失敗.

sentinel 測試
實驗環境 < one master / Three slaves / two sentinels >:
a. one master(slave-priority爲90)部署在ip爲192.168.9.10的機器上;
b.Three slaves(slave-priority分別爲100)的均部署在ip爲192.168.9.70的機器上;
c. 啓用兩個sentinel進程監控redis集羣狀態

配置 sentinel

Sentinel可以通過master Redis實例來獲得它的從實例的信息.所以每一個Sentinel只配置主實例的監控即可.Sentinel之間端口有所不同.

port 6666
  daemonize yes
  logfile "/var/log/redis/sentinel-6666.log"
 
  #master 1111
  sentinel monitor master-1111 192.168.9.10 11111 1
  sentinel config-epoch master-1111 6
  sentinel leader-epoch master-1111 6
  sentinel known-slave master-1111 192.168.9.70 2222

啓動 sentinel
配置文件修改完成後,啓動各監控進程即可,例如:
redis-server /etc/redis/sentinel-6666.conf

連接Sentinel和主動failover

在默認情況下,Sentinel 使用TCP端口26379(普通 Redis 服務器使用的是 6379).
Sentinel 接受 Redis 協議格式的命令請求,所以你可以使用 redis-cli 或者任何其他 Redis 客戶端來與 Sentinel 進行通訊.
有兩種方式可以和 Sentinel 進行通訊:
第一種方法是通過直接發送命令來查詢被監視 Redis 服務器的當前狀態, 以及進行主動轉移等操作.這些命令包括:

SENTINEL masters
列出所有被監視的主Redis服務實例,以及這些主服務實例的當前狀態.

SENTINEL slaves
列出給定主服務實例的所有從實例,以及這些從實例的當前狀態.

SENTINEL get-master-addr-by-name
返回給定名字的主實例的 IP 地址和端口號. 如果這個主實例正在執行故障轉移操作, 或者針對這個主實例的故障轉移操作已經完成, 那麼這個命令返回新的主服務器的 IP 地址和端口號.

SENTINEL reset:
重置所有名字和給定模式 pattern 相匹配的主服務器. pattern 參數是一個 Glob 風格的模式. 重置操作清除該sentinel的所保存的所有狀態信息,並進行一次重新的發現過程.

SENTINEL failover
進行一次主動的failover.即在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移 .發起故障轉移的 Sentinel 會向其他 Sentinel 發送一個新的配置,其他 Sentinel 會根據這個配置進行相應的更新.

^_^[17:19:25][root@master01 ~]#redis-cli  -p 6666
redis 127.0.0.1:6666> SENTINEL masters
1)  1) "name"
2) "master-1111"
3) "ip"
4) "192.168.9.10"
5) "port"
6) "1111"
7) "runid"
8) "5d6c2f08547ffe9446eb54c85dc40959e66b203d"
9) "flags"
10) "master"
11) "pending-commands"
12) "0"
13) "last-ping-sent"
14) "0"
15) "last-ok-ping-reply"
16) "947"
17) "last-ping-reply"
18) "947"
19) "down-after-milliseconds"
20) "30000"
21) "info-refresh"
22) "6259"
23) "role-reported"
24) "master"
25) "role-reported-time"
26) "126884"
27) "config-epoch"
28) "7"
29) "num-slaves"
30) "3"
31) "num-other-sentinels"
32) "1"
33) "quorum"
34) "1"
35) "failover-timeout"
36) "180000"
37) "parallel-syncs"
38) "1"

redis 127.0.0.1:6666> SENTINEL slaves master-1111
1)  1) "name"
2) "192.168.9.10:1112"
3) "ip"
4) "192.168.9.10"
5) "port"
6) "1112"
7) "runid"
8) ""
9) "flags"
10) "s_down,slave,disconnected"
11) "pending-commands"
12) "0"
13) "last-ping-sent"
14) "215549"
15) "last-ok-ping-reply"
16) "215549"
17) "last-ping-reply"
18) "215549"
19) "s-down-time"
20) "185544"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "1458206565223"
25) "role-reported"
26) "slave"
27) "role-reported-time"
28) "215549"
29) "master-link-down-time"
30) "0"
31) "master-link-status"
32) "err"
33) "master-host"
34) "?"
35) "master-port"
36) "0"
37) "slave-priority"
38) "100"
39) "slave-repl-offset"
40) "0"
2)  1) "name"
2) "192.168.9.70:2222"
3) "ip"
4) "192.168.9.70"
5) "port"
6) "2222"
7) "runid"
8) ""
9) "flags"
10) "s_down,slave,disconnected"
11) "pending-commands"
12) "0"
13) "last-ping-sent"
14) "215549"
15) "last-ok-ping-reply"
16) "215549"
17) "last-ping-reply"
18) "215549"
19) "s-down-time"
20) "185544"
21) "down-after-milliseconds"
22) "30000"
23) "info-refresh"
24) "1458206565223"
25) "role-reported"
26) "slave"
27) "role-reported-time"
28) "215549"
29) "master-link-down-time"
30) "0"
31) "master-link-status"
32) "err"
33) "master-host"
34) "?"
35) "master-port"
36) "0"
37) "slave-priority"
38) "100"
39) "slave-repl-offset"
40) "0"
3)  1) "name"
2) "192.168.9.70:2223"
3) "ip"
4) "192.168.9.70"
5) "port"
6) "2223"
7) "runid"
8) "9987aebafc55d750145a61f9109cf7d9fb7c8613"
9) "flags"
10) "slave"
11) "pending-commands"
12) "0"
13) "last-ping-sent"
14) "0"
15) "last-ok-ping-reply"
16) "372"
17) "last-ping-reply"
18) "372"
19) "down-after-milliseconds"
20) "30000"
21) "info-refresh"
22) "4616"
23) "role-reported"
24) "slave"
25) "role-reported-time"
26) "215549"
27) "master-link-down-time"
28) "0"
29) "master-link-status"
30) "ok"
31) "master-host"
32) "192.168.9.10"
33) "master-port"
34) "1111"
35) "slave-priority"
36) "100"
37) "slave-repl-offset"
38) "29082"

查看當前的master
redis 127.0.0.1:6666>  SENTINEL get-master-addr-by-name master-1111
1) "192.168.9.10"
2) "1111"

 

使用發佈與訂閱功能, 通過接收 Sentinel 發送的通知: 當執行故障轉移操作, 或者某個被監視的實例被判斷爲主觀下線或者客觀下線時, Sentinel 就會發送相應的信息.
一個頻道能夠接收和這個頻道的名字相同的事件. 比如說,名爲 +sdown 的頻道就可以接收所有實例進入主觀下線(SDOWN)狀態的事件.
通過執行 PSUBSCRIBE * 命令可以接收所有事件信息.例如:

^_^[17:50:13][root@master01 ~]#redis-cli -p 6666 info| grep 192
master0:name=master-1111,status=ok,address=192.168.9.10:1111,slaves=3,sentinels=2

^_^[17:50:21][root@master01 ~]#redis-cli -p 6666 sentinel failover master-1111
OK

@_@[17:50:09][root@master01 ~]#redis-cli -p 6666
redis 127.0.0.1:6666>  SENTINEL get-master-addr-by-name master-1111
1) "192.168.9.10"
2) "1111"
redis 127.0.0.1:6666> PSUBSCRIBE *
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*"
3) (integer) 1
1) "pmessage"
2) "*"
3) "+new-epoch"
4) "8"
1) "pmessage"
2) "*"
3) "+try-failover"
4) "master master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+vote-for-leader"
4) "691dc32d3a3c1afdc5b18a8e5541c885aa04c487 8"
1) "pmessage"
2) "*"
3) "+elected-leader"
4) "master master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+failover-state-select-slave"
4) "master master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+selected-slave"
4) "slave 192.168.9.10:1112 192.168.9.10 1112 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+failover-state-send-slaveof-noone"
4) "slave 192.168.9.10:1112 192.168.9.10 1112 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+failover-state-wait-promotion"
4) "slave 192.168.9.10:1112 192.168.9.10 1112 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "-role-change"
4) "slave 192.168.9.10:1112 192.168.9.10 1112 @ master-1111 192.168.9.10 1111 new reported role is master"
1) "pmessage"
2) "*"
3) "+promoted-slave"
4) "slave 192.168.9.10:1112 192.168.9.10 1112 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+failover-state-reconf-slaves"
4) "master master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+slave-reconf-sent"
4) "slave 192.168.9.70:2222 192.168.9.70 2222 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+slave-reconf-inprog"
4) "slave 192.168.9.70:2222 192.168.9.70 2222 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+slave-reconf-done"
4) "slave 192.168.9.70:2222 192.168.9.70 2222 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+slave-reconf-sent"
4) "slave 192.168.9.70:2223 192.168.9.70 2223 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+slave-reconf-inprog"
4) "slave 192.168.9.70:2223 192.168.9.70 2223 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+slave-reconf-done"
4) "slave 192.168.9.70:2223 192.168.9.70 2223 @ master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+failover-end"
4) "master master-1111 192.168.9.10 1111"
1) "pmessage"
2) "*"
3) "+switch-master"
4) "master-1111 192.168.9.10 1111 192.168.9.10 1112"
1) "pmessage"
2) "*"
3) "+slave"
4) "slave 192.168.9.70:2222 192.168.9.70 2222 @ master-1111 192.168.9.10 1112"
1) "pmessage"
2) "*"
3) "+slave"
4) "slave 192.168.9.70:2223 192.168.9.70 2223 @ master-1111 192.168.9.10 1112"
1) "pmessage"
2) "*"
3) "+slave"
4) "slave 192.168.9.10:1111 192.168.9.10 1111 @ master-1111 192.168.9.10 1112"
1) "pmessage"
2) "*"
3) "-role-change"
4) "slave 192.168.9.10:1111 192.168.9.10 1111 @ master-1111 192.168.9.10 1112 new reported role is master"
1) "pmessage"
2) "*"
3) "+role-change"
4) "slave 192.168.9.10:1111 192.168.9.10 1111 @ master-1111 192.168.9.10 1112 new reported role is slave"

一次故障轉移操作由以下步驟組成:
(1). 由sentinel主動發起failover或者發現主服務器已經進入客觀下線狀態.
(2). sentinel對我們的當前紀元(epoch)進行自增,並嘗試在這個紀元中當選爲此次failover的總指揮.
(3). 如果當選失敗, 那麼在設定的故障遷移超時時間的兩倍之後, 重新嘗試當選. 如果當選成功, 那麼執行以下步驟.
(4). 選出一個從redis實例,並將它升級爲主redis實例.
(5). 向被選中的從redis實例發送 SLAVEOF NO ONE 命令,讓它轉變爲主redis實例.
(6). 通過發佈與訂閱功能, 將更新後的配置傳播給所有其他 Sentinel , 其他 Sentinel 對它們自己的配置進行更新.
(7). 向已下線主服務器的從服務器發送SLAVEOF命令, 讓它們去複製新的主服務器.
(8). 當所有從redis實例都已經開始複製新的主redis實例時, 領頭Sentinel 終止這次故障遷移操作.


FAQ:
若master實例故障,則最好等sentinel選出new master且穩定後(選新主並完成切換的時間與配置有關,典型值在1分鐘之內),再重啓old master,避免引發sentinel的誤判,導致整個系統無法選出new master.

最大內存問題:要設置好最大內存,以防不停的申請內存,造成系統內存都被用完.

Fork進程問題:’vm.overcommit_memory = 1’這一個選項要加到系統的配置中,防止fork因內存不足而失敗.

密碼問題:需要設置複雜一些,防止暴力破解.


 License:Attribution-NonCommercial-NoDerivatives 4.0 International
 本文出自 Suzf Blog。 如未註明,均爲 SUZF.NET 原創。
 轉載請註明出處:http://suzf.net/thread-0317-627.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章