Redis Sentinel 概述
Redis Sentinel 是 Redis 官方提供的高可用性解決方案。它可以自動監控 Redis 主從節點的運作狀態,並在主節點發生故障時,自動將其中一個從節點提升為新的主節點,確保服務持續運作。
Sentinel 主要功能
- 監控(Monitoring):持續檢查主節點和從節點是否正常運作
- 通知(Notification):當被監控的 Redis 實例發生問題時,可透過 API 通知系統管理員
- 自動故障轉移(Automatic Failover):當主節點失效時,自動將從節點提升為主節點
- 設定提供者(Configuration Provider):客戶端可透過 Sentinel 取得目前主節點的位址
適用場景
- 需要高可用性的生產環境
- 讀取流量較大,需要讀寫分離的場景
- 對服務中斷時間有嚴格要求的應用
架構說明
本文將建置 1 Master + 2 Slaves + 3 Sentinels 的高可用架構。
伺服器規劃
| 角色 | IP 位址 | 連接埠 |
|---|
| Redis Master | 192.168.1.10 | 6379 |
| Redis Slave 1 | 192.168.1.11 | 6379 |
| Redis Slave 2 | 192.168.1.12 | 6379 |
| Sentinel 1 | 192.168.1.10 | 26379 |
| Sentinel 2 | 192.168.1.11 | 26379 |
| Sentinel 3 | 192.168.1.12 | 26379 |
架構圖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| +----------------+
| Application |
+-------+--------+
|
+-------v--------+
| Sentinels |
| (監控與故障轉移) |
+-------+--------+
|
+-------------------+-------------------+
| | |
+-------v-------+ +-------v-------+ +-------v-------+
| Redis Master | | Redis Slave 1 | | Redis Slave 2 |
| 192.168.1.10 | | 192.168.1.11 | | 192.168.1.12 |
+---------------+ +---------------+ +---------------+
|
環境準備
在所有節點上安裝 Redis
首先在三台伺服器上安裝 Redis:
1
2
| sudo apt update
sudo apt install redis-server -y
|
設定防火牆
開放必要的連接埠:
1
2
3
4
5
6
7
8
| # 開放 Redis 連接埠
sudo ufw allow 6379/tcp
# 開放 Sentinel 連接埠
sudo ufw allow 26379/tcp
# 重新載入防火牆規則
sudo ufw reload
|
Redis Master 設定
編輯主節點的設定檔 /etc/redis/redis.conf:
1
| sudo nano /etc/redis/redis.conf
|
修改以下設定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| # 綁定所有網路介面
bind 0.0.0.0
# 設定連接埠
port 6379
# 關閉保護模式(因為有密碼保護)
protected-mode no
# 設定密碼
requirepass your_redis_password
# 設定主從複製密碼(從節點連接時使用)
masterauth your_redis_password
# 啟用 AOF 持久化
appendonly yes
# 設定 RDB 持久化
save 900 1
save 300 10
save 60 10000
|
重新啟動 Redis:
1
2
| sudo systemctl restart redis-server
sudo systemctl status redis-server
|
Redis Slave 設定
在兩台從節點(192.168.1.11 和 192.168.1.12)上編輯設定檔:
1
| sudo nano /etc/redis/redis.conf
|
修改以下設定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # 綁定所有網路介面
bind 0.0.0.0
# 設定連接埠
port 6379
# 關閉保護模式
protected-mode no
# 設定密碼
requirepass your_redis_password
# 設定主從複製密碼
masterauth your_redis_password
# 設定主節點位址(關鍵設定)
replicaof 192.168.1.10 6379
# 啟用 AOF 持久化
appendonly yes
# 從節點設定為唯讀
replica-read-only yes
|
重新啟動 Redis:
1
2
| sudo systemctl restart redis-server
sudo systemctl status redis-server
|
驗證主從複製
在主節點上檢查複製狀態:
1
| redis-cli -a your_redis_password INFO replication
|
應該看到類似以下輸出:
1
2
3
4
5
| # Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.11,port=6379,state=online,offset=xxx,lag=0
slave1:ip=192.168.1.12,port=6379,state=online,offset=xxx,lag=0
|
Sentinel 設定檔
在三台伺服器上建立 Sentinel 設定檔:
1
| sudo nano /etc/redis/sentinel.conf
|
Sentinel 設定檔內容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| # Sentinel 連接埠
port 26379
# 綁定所有網路介面
bind 0.0.0.0
# 關閉保護模式
protected-mode no
# 以背景程序執行
daemonize yes
# PID 檔案位置
pidfile /var/run/redis/redis-sentinel.pid
# Log 檔案位置
logfile /var/log/redis/redis-sentinel.log
# 工作目錄
dir /var/lib/redis
# 監控的主節點設定
# sentinel monitor <master-name> <ip> <port> <quorum>
# quorum:需要多少個 Sentinel 同意才進行故障轉移
sentinel monitor mymaster 192.168.1.10 6379 2
# 主節點密碼
sentinel auth-pass mymaster your_redis_password
# 判定主節點下線的時間(毫秒)
sentinel down-after-milliseconds mymaster 5000
# 故障轉移超時時間(毫秒)
sentinel failover-timeout mymaster 60000
# 同時進行同步的從節點數量
sentinel parallel-syncs mymaster 1
|
設定檔案權限:
1
2
| sudo chown redis:redis /etc/redis/sentinel.conf
sudo chmod 640 /etc/redis/sentinel.conf
|
啟動 Sentinel
建立 Systemd 服務
建立 Sentinel 的 systemd 服務檔案:
1
| sudo nano /etc/systemd/system/redis-sentinel.service
|
內容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| [Unit]
Description=Redis Sentinel
After=network.target
[Service]
Type=forking
ExecStart=/usr/bin/redis-sentinel /etc/redis/sentinel.conf
ExecStop=/usr/bin/redis-cli -p 26379 shutdown
PIDFile=/var/run/redis/redis-sentinel.pid
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
|
啟動服務
1
2
3
4
5
6
7
8
9
10
11
| # 重新載入 systemd 設定
sudo systemctl daemon-reload
# 啟動 Sentinel
sudo systemctl start redis-sentinel
# 設定開機自動啟動
sudo systemctl enable redis-sentinel
# 檢查狀態
sudo systemctl status redis-sentinel
|
驗證 Sentinel 運作
檢查 Sentinel 狀態:
1
| redis-cli -p 26379 INFO sentinel
|
應該看到類似輸出:
1
2
3
4
5
6
7
| # 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=192.168.1.10:6379,slaves=2,sentinels=3
|
查詢目前主節點:
1
| redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
|
故障轉移測試
模擬主節點故障
在主節點上停止 Redis 服務:
1
| sudo systemctl stop redis-server
|
觀察 Sentinel 日誌
在任一 Sentinel 節點上查看日誌:
1
| sudo tail -f /var/log/redis/redis-sentinel.log
|
您應該看到類似以下的故障轉移過程:
1
2
3
4
5
6
7
8
9
10
11
| +sdown master mymaster 192.168.1.10 6379
+odown master mymaster 192.168.1.10 6379 #quorum 2/2
+try-failover master mymaster 192.168.1.10 6379
+vote-for-leader xxx 1
+elected-leader master mymaster 192.168.1.10 6379
+failover-state-select-slave master mymaster 192.168.1.10 6379
+selected-slave slave 192.168.1.11:6379
+failover-state-send-slaveof-noone slave 192.168.1.11:6379
+failover-state-wait-promotion slave 192.168.1.11:6379
+promoted-slave slave 192.168.1.11:6379
+switch-master mymaster 192.168.1.10 6379 192.168.1.11 6379
|
確認新主節點
1
| redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
|
恢復原主節點
重新啟動原主節點,它會自動成為新主節點的從節點:
1
| sudo systemctl start redis-server
|
應用程式連線設定
Python 連線範例
使用 redis-py 套件連接 Sentinel:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| from redis.sentinel import Sentinel
# Sentinel 節點列表
sentinel = Sentinel([
('192.168.1.10', 26379),
('192.168.1.11', 26379),
('192.168.1.12', 26379)
], socket_timeout=0.5)
# 取得主節點連線(用於寫入)
master = sentinel.master_for('mymaster', socket_timeout=0.5, password='your_redis_password')
# 取得從節點連線(用於讀取)
slave = sentinel.slave_for('mymaster', socket_timeout=0.5, password='your_redis_password')
# 寫入資料
master.set('key', 'value')
# 讀取資料
value = slave.get('key')
print(value)
|
Node.js 連線範例
使用 ioredis 套件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| const Redis = require('ioredis');
const redis = new Redis({
sentinels: [
{ host: '192.168.1.10', port: 26379 },
{ host: '192.168.1.11', port: 26379 },
{ host: '192.168.1.12', port: 26379 }
],
name: 'mymaster',
password: 'your_redis_password'
});
redis.set('key', 'value');
redis.get('key', (err, result) => {
console.log(result);
});
|
維運建議
監控指標
建議監控以下指標:
- Sentinel 連線狀態
- 主從複製延遲(replication lag)
- 記憶體使用量
- 連線數量
日常維護
1
2
3
4
5
6
7
8
| # 檢查 Sentinel 狀態
redis-cli -p 26379 SENTINEL masters
# 檢查從節點狀態
redis-cli -p 26379 SENTINEL slaves mymaster
# 手動故障轉移
redis-cli -p 26379 SENTINEL failover mymaster
|
參考資料