前置知识: Redis

哨兵选举

00:00
2 min Advanced 2026/6/14

Redis Sentinel 哨兵选举机制:主观下线、客观下线、Leader 选举与 Raft 算法、故障转移流程。

1. Sentinel 架构

1.1 Sentinel 集群

┌──────────┐  ┌──────────┐  ┌──────────┐
│Sentinel 1│  │Sentinel 2│  │Sentinel 3│
└─────┬────┘  └─────┬────┘  └─────┬────┘
      │             │             │
      └─────────────┼─────────────┘
                    │ 监控
      ┌─────────────┼─────────────┐
      ↓             ↓             ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│  Master  │ │ Replica1 │ │ Replica2 │
└──────────┘ └──────────┘ └──────────┘

1.2 Sentinel 职责

  • 监控:持续检测主从是否正常
  • 通知:故障时通知管理员或应用
  • 自动故障转移:主故障时自动切换
  • 配置提供者:告知客户端当前主地址

2. 下线检测

2.1 主观下线(SDOWN)

个 Sentinel 认为节点不可用:

Sentinel 每秒向节点发送 PING
超过 down-after-milliseconds 无有效回复 → 标记为 SDOWN
# 配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000

2.2 客观下线(ODOWN)

个 Sentinel 都认为主不可用:

1. Sentinel A 检测到 Master SDOWN
2. Sentinel A 向其他 Sentinel 发送 SENTINEL is-master-down-by-addr
3. 超过 quorum 个 Sentinel 确认 SDOWN → 标记为 ODOWN
4. ODOWN 触发故障转移

quorum配置sentinel monitor 的最后一个参数表示需要少个 Sentinel 同意才能判定客观下线。

3. Leader 选举(Raft 算法)

3.1 为什么需要 Leader

只有被选为 Leader 的 Sentinel 才能执行故障转移,避免个 Sentinel 同时执行

3.2 Raft 选举流程

1. Sentinel 确认 Master ODOWN
2. Sentinel 自增 current_epoch(任期号)
3. 向其他 Sentinel 请求投票(SENTINEL is-master-down-by-addr)
4. 其他 Sentinel 每个任期只投一票(先到先得)
5. 获得多数票(> N/2)的 Sentinel 成为 Leader
6. Leader 执行故障转移

3.3 选举规则

规则1: 先到先得(FIFO)— 每个 epoch 只投一票
规则2: 获得多数票 — > ceil(N/2),N 为 Sentinel 总数
规则3: epoch 递增 — 新选举的 epoch 必须大于当前值

选举示例(3个 Sentinel):

Sentinel A: epoch=1, 请求投票 → 获得 A(自投), B → 2票 > 1.5 → 成为 Leader
Sentinel B: epoch=1, 请求投票 → 已投给A → 拒绝
Sentinel C: epoch=1, 请求投票 → 已投给A → 拒绝

3.4 选举超时与重试

如果未获得多数票:
  等待随机时间(避免同时发起选举)
  自增 epoch
  重新请求投票

最大重试次数: 无限制
超时时间: 故障转移超时(failover-timeout)

4. 故障转移

4.1 从库选择规则

Leader Sentinel 按以下规则选择新主

1. 排除下线或断线的从库
2. 排除最近5秒内未回复 INFO 的从库
3. 排除与旧主库断开时间过长的从库
   (down-after-milliseconds * 10)
4. 按优先级选择(replica-priority 越小越优先)
5. 优先级相同,选择复制偏移量最大的(数据最新)
6. 偏移量相同,选择 runid 最小的

4.2 故障转移步骤

步骤1: 选出新主库
  Leader Sentinel 根据上述规则选出最优从库

步骤2: 升级新主库
  SENTINEL SLAVEOF NO ONE → 新主库停止复制

步骤3: 修改其他从库的复制目标
  其他从库执行 SLAVEOF new_master

步骤4: 更新 Sentinel 配置
  所有 Sentinel 更新 Master 地址

步骤5: 通知客户端
  客户端通过 Sentinel 获取新 Master 地址

4.3 故障转移时间线

T+0s:    Master 下线
T+30s:   Sentinel 检测到 SDOWN(down-after-milliseconds=30s)
T+31s:   确认 ODOWN,发起 Leader 选举
T+32s:   Leader 选举完成
T+33s:   选出新主库,执行 SLAVEOF NO ONE
T+35s:   其他从库开始复制新主库
T+40s:   故障转移完成

5. Sentinel 配置最佳实践

5.1 推荐配置

# 至少3个 Sentinel(保证多数票)
sentinel monitor mymaster 127.0.0.1 6379 2

# down-after-milliseconds: 根据网络延迟调整
sentinel down-after-milliseconds mymaster 10000

# failover-timeout: 故障转移超时
sentinel failover-timeout mymaster 60000

# parallel-syncs: 故障转移后同时向新主库发起复制的从库数
sentinel parallel-syncs mymaster 1

5.2 quorum 设置

quorum 建议值: ceil(N/2),N 为 Sentinel 数量

3个 Sentinel: quorum=2
5个 Sentinel: quorum=3

quorum 过低: 可能误判(网络分区时)
quorum 过高: 可能无法触发故障转移

5.3 客户端连接

# Python 客户端通过 Sentinel 获取 Master
from redis.sentinel import Sentinel

sentinel = Sentinel([
    ('sentinel1', 26379),
    ('sentinel2', 26379),
    ('sentinel3', 26379)
], socket_timeout=0.1)

master = sentinel.master_for('mymaster', password='xxx')
slave = sentinel.slave_for('mymester', password='xxx')

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式