Redis Master-Slave Sentinel (哨兵模式)

前言

繼上一篇 w4560000 - Redis Master-Slave 建置完 Redis Master-Slave 主從複製機制後,接著研究哨兵模式

在以往單體 Redis 服務異常當下,會需要維運人員手動介入處理
而若使用 Master-Slave 機制時,當 Master 發生異常,Redis 可透過 Sentinel (哨兵機制) 從 Slave 中選出一個來當 Master

環境

Linux VM = ubuntu-2004-lts
Redis Docker映像檔 = redis:6.0.0

Master、Slave 建置參考上一篇 w4560000 - Redis Master-Slave#環境

本篇接續建立 3 台 Redis Sentinel (哨兵機制),加上原有的 Master、Slave,共有 6 台

機器 IP
redis-master 10.140.0.20
redis-slave-1 10.140.0.21
redis-slave-2 10.140.0.22
redis-sentinel-1 10.140.0.11
redis-sentinel-2 10.140.0.12
redis-sentinel-3 10.140.0.13

設定 VM

建立 3 台 Sentinel 機器

for i in 1 2 3; do
  gcloud compute instances create redis-sentinel-${i} \
    --async \
    --boot-disk-size 100GB \
    --can-ip-forward \
    --image-family ubuntu-2004-lts \
    --image-project ubuntu-os-cloud \
    --machine-type e2-standard-2 \
    --private-network-ip 10.240.0.1${i} \
    --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
    --subnet redis-vpc-subnet \
    --zone asia-east1-a \
    --tags redis-vpc
done

安裝 Docker

參考 w4560000 - Linux 安裝 Docker、Docker-Compose

3 台 VM 都先設定好 volumn 資料夾

mkdir redis && mkdir redisdata

建置 Sentinel (哨兵機制)

設定 sentinel.conf

哨兵數量需為 2n +1 (n >= 1),需為奇數才能投票

  • sentinel monitor

    設定要監控的 Master、最後的數字代表有幾個哨兵判斷 Master 異常,才算判定異常
    建議設定 (哨兵數 / 2) +1
    ex: sentinel monitor mymaster 10.240.0.20 6379 2

  • sentinel down-after-milliseconds

    判斷 Master 是否存活,預設是 30 秒,若超過時間則會被判定異常
    ex: sentinel down-after-milliseconds mymaster 30000

  • sentinel failover-timeout

    故障轉移超時時間
    ex: sentinel failover-timeout mymaster 180000

  • parallel-syncs

  • 故障轉移期間,允許多少個 Slave 同時向新的 Master 同步資料,預設是 1 個

    ex: parallel-syncs mymaster 1

  • sentinel announce-ip

  • sentinel announce-port

    暴露IP、Port
    Redis 的 sentinel 會宣告自己的IP、Port,讓其他 sentinel 監聽
    在 Docker 環境會因為容器內 IP,與主機 IP 不同,導致其他 semtinel 是監聽到容器內的 IP,而不是主機 IP
    可透過這兩個參數來指定主機 IP、Port
    ex: sentinel announce-ip 10.240.0.11
    ex: sentinel announce-port 26379

參考 Redis 官方文件 - Sentinel, Docker, NAT, and possible issues

sentinel-1、sentinel-2、sentinel-3
路徑 ~/redis/sentinel.conf
分別建立 sentinel.conf

sentinel-1

port 26379
sentinel monitor mymaster 10.240.0.20 6379 2
sentinel down-after-milliseconds mymaster 1000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
sentinel announce-ip 10.240.0.11
sentinel announce-port 26379

sentinel-2

port 26379
sentinel monitor mymaster 10.240.0.20 6379 2
sentinel down-after-milliseconds mymaster 1000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
sentinel announce-ip 10.240.0.12
sentinel announce-port 26379

sentinel-3

port 26379
sentinel monitor mymaster 10.240.0.20 6379 2
sentinel down-after-milliseconds mymaster 1000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
sentinel announce-ip 10.240.0.13
sentinel announce-port 26379

設定 Master、Slave redis.conf 權限

Master、Slave 設定權限

sudo chmod 777 redis/redis.conf

當故障轉移時,Redis 會修改 redis.conf,所以需要設定權限

假設當 Master 異常時,轉移 Master 給 Slave2,而 Redis 就會自動修改 Master、Slave1、Slave2 的 Redis.conf
ex:

機器 修改前 修改後
redis-master replicaof 10.240.0.22 6379
redis-slave-1 replicaof 10.240.0.20 6379 replicaof 10.240.0.22 6379
redis-slave-2 replicaof 10.240.0.20 6379

設定 Sentinel sentinel.conf 權限

sudo chmod 777 redis/sentinel.conf

若沒有設定會出現異常 Sentinel config file /usr/local/etc/redis/sentinel.conf is not writable: Permission denied

啟動 Sentinel 服務

三台 Sentinel 建立 redis-sentinel

docker run --name redis-sentinel \
-p 26379:26379 \
-v /home/leozheng0411/redis:/usr/local/etc/redis \
-v /home/leozheng0411/redisdata:/data \
-d redis:6.0.0 \
redis-server /usr/local/etc/redis/sentinel.conf --sentinel

災難異常復原模擬

目前配置

機器 IP
redis-master 10.140.0.20
redis-slave-1 10.140.0.21
redis-slave-2 10.140.0.22
redis-sentinel-1 10.140.0.11
redis-sentinel-2 10.140.0.12
redis-sentinel-3 10.140.0.13

先確認服務是否建置成功

redis-master

docker exec -it redis-master redis-cli info replication

# 輸出
# Replication
role:master
connected_slaves:2
slave0:ip=10.240.0.21,port=6379,state=online,offset=19852,lag=1
slave1:ip=10.240.0.22,port=6379,state=online,offset=19852,lag=1
master_replid:97d66f61b367b1f49b5c9ff233a3722553d94f65
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:19852
master_repl_meaningful_offset:19838
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:19852

redis-sentinel-1

docker exec -it redis-sentinel redis-cli -p 26379 info sentinel

# 輸出
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=10.240.0.20:6379,slaves=2,sentinels=3

測試流程如下

  1. 停用 redis-master

redis-master

docker rm -f redis-master
  1. 確認 redis-sentinel 是否有操作故障轉移

redis-sentinel-1

docker logs redis-sentinel

# 輸出
1:X 20 Jun 2023 07:53:36.998 # +sdown master mymaster 10.240.0.20 6379
1:X 20 Jun 2023 07:53:37.054 # +odown master mymaster 10.240.0.20 6379 #quorum 3/2
1:X 20 Jun 2023 07:53:37.054 # +new-epoch 1
1:X 20 Jun 2023 07:53:37.054 # +try-failover master mymaster 10.240.0.20 6379
1:X 20 Jun 2023 07:53:37.082 # +vote-for-leader 761245a97aa658488cdc866cac6b23b6a8cc04ef 1
1:X 20 Jun 2023 07:53:37.083 # f48158aed0b646e2e8dda0091735ac072829d7ef voted for f48158aed0b646e2e8dda0091735ac072829d7ef 1
1:X 20 Jun 2023 07:53:37.120 # a0cb3eb2fe013e9d2c389af6bbd314dff671c874 voted for f48158aed0b646e2e8dda0091735ac072829d7ef 1
1:X 20 Jun 2023 07:53:38.076 # +config-update-from sentinel f48158aed0b646e2e8dda0091735ac072829d7ef 10.240.0.12 26379 @ mymaster 10.240.0.20 6379
1:X 20 Jun 2023 07:53:38.076 # +switch-master mymaster 10.240.0.20 6379 10.240.0.22 6379
1:X 20 Jun 2023 07:53:38.076 * +slave slave 10.240.0.21:6379 10.240.0.21 6379 @ mymaster 10.240.0.22 6379
1:X 20 Jun 2023 07:53:38.076 * +slave slave 10.240.0.20:6379 10.240.0.20 6379 @ mymaster 10.240.0.22 6379

Master 被轉移給 redis-slave-2 (10.240.0.22)

  1. 確認新 Master,更新資料後,是否會同步給另一個 Slave

redis-slave-1

docker exec -it redis-slave redis-cli get Key1

# 輸出
(nil)

redis-slave-2

docker exec -it redis-slave redis-cli set Key1 "1"

redis-slave-1

docker exec -it redis-slave redis-cli get Key1

# 輸出
"1"

redis-slave-2 (新 Master) 寫入資料後,會同步更新 redis-slave-1

  1. 重啟 redis-master,確認是否會同步新 Master 的資料,確保資料一致

redis-master

docker run --name redis-master \
-p 6379:6379 \
-v /home/leozheng0411/redis:/usr/local/etc/redis \
-v /home/leozheng0411/redisdata:/data \
-d redis:6.0.0 \
redis-server /usr/local/etc/redis/redis.conf

docker exec -it redis-master redis-cli get Key1

# 輸出
"1"

redis-master 重啟後,會被 Sentinel 在 redis.conf 新增 replicaof <新Master>

補充

sdown (主觀下線)

當 Redis Sentinel 依照 down-after-milliseconds 的設定,判斷 Master 沒回應時,會判定主觀下線 (+sdown)
此時會詢問其他 Sentinel 來判定,當其他 Sentinel +sdown 的票數達到 sentinel monitor 設定的 quorum 時,則會被判定成 +odown

odown (客端下線)

當其他 Sentinel +sdown 的票數達到 sentinel monitor 設定的 quorum 時,則會被判定成 +odown
當 Master 被判斷成 +odown,則開始啟動 failover 機制

若移除主觀下線、客端下線標記則為 -sdown 、 -odown

參考文件

HackMD tienyulin - Redis (六) - 主從複製、哨兵與叢集模式#哨兵模式
TPIU 吳建男 Lancelot Wu - Redis sentinel 簡介與部署
博客園 SlowTech - 深入理解Redis高可用方案-Sentinel
博客園 DBA’s Record - Redis Sentinel机制与用法说明【转】


轉載請註明來源,若有任何錯誤或表達不清楚的地方,歡迎在下方評論區留言,也可以來信至 leozheng0621@gmail.com
如果文章對您有幫助,歡迎斗內(donate),請我喝杯咖啡

斗內💰

×

歡迎斗內

github