跳到主要内容

Redis 哨兵 (Sentinel)

Redis Sentinel 是 Redis 的高可用解决方案,它提供自动监控、通知、故障转移和配置提供功能。在没有使用 Redis Cluster 的情况下,Sentinel 是实现高可用的最佳选择。

哨兵的核心功能

四大核心能力

  1. 监控 (Monitoring):持续检查主库和从库是否运行正常,自动发现节点变更
  2. 通知 (Notification):故障发生时通过 API 通知管理员或系统,支持订阅系统事件
  3. 自动故障转移 (Automatic Failover):主库故障时,从从库中选举新主库,让其他从库指向新主库
  4. 配置中心 (Configuration Provider):客户端连接哨兵获取主库地址,发生主从切换时客户端会得到更新

Sentinel 作为分布式系统

Sentinel 本身设计为多个进程协作运行的分布式系统:

  • 降低误判:多个 Sentinel 同意某主库不可用时才判定故障
  • 系统健壮性:即使部分 Sentinel 故障,系统仍能正常工作

故障判定机制

主观下线 (SDOWN)

单个 Sentinel 节点在 down-after-milliseconds 时间内无法联系到主库,则判定为主观下线。

# Sentinel 配置
sentinel down-after-milliseconds mymaster 30000 # 30 秒无响应判定为主观下线

客观下线 (ODOWN)

当超过 quorum(法定人数)数量的 Sentinel 都认为主库已下线,则判定为客观下线。只有判定为客观下线后,才会触发故障转移。

# quorum = 2 表示需要 2 个 Sentinel 同意才判定为客观下线
sentinel monitor mymaster 127.0.0.1 6379 2

Quorum 与 Majority 的区别

Quorum:判定故障所需的 Sentinel 数量 Majority:授权故障转移所需的 Sentinel 多数票

例如,5 个 Sentinel,quorum = 2:

  • 2 个 Sentinel 同意即可判定故障
  • 但需要至少 3 个 Sentinel(多数)才能授权故障转移

故障转移流程

完整流程

  1. 选举领头 Sentinel:Sentinel 集群通过 Raft 类似的算法选出一个 Leader 负责执行故障转移
  2. 选出新主库
    • 排除下线的从库
    • 排除最近断开连接过久的从库
    • 优先级:根据 replica-priority(越小越高)
    • 偏移量:选择复制偏移量最大的(数据最全)
    • Run ID:如果以上相同,选择 Run ID 最小的
  3. 配置转移:让原有从库执行 REPLICAOF 新主库
  4. 旧主归队:当旧主库上线后,Sentinel 会将其降级为新主库的从库

故障转移示例

时间线:
T1: Master 故障,Sentinel 开始检测
T2: 达到 down-after-milliseconds,标记为 SDOWN
T3: quorum 个 Sentinel 同意,标记为 ODOWN
T4: 选举领头 Sentinel
T5: 从从库中选举新 Master
T6: 其他从库复制新 Master
T7: 更新客户端配置
T8: 旧 Master 恢复后成为新 Master 的从库

配置与部署

哨兵配置文件 (sentinel.conf)

# 端口(默认 26379)
port 26379

# 监控主库
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 192.168.1.100 6379 2

# 主库密码(如果设置了)
sentinel auth-pass mymaster your_password

# 主观下线判定时间(毫秒)
sentinel down-after-milliseconds mymaster 30000

# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 180000

# 同时向新主库发起同步的从库数量
sentinel parallel-syncs mymaster 1

# 工作目录
dir /tmp

配置参数详解

参数说明默认值
down-after-milliseconds主观下线判定时间30000ms
failover-timeout故障转移超时时间180000ms
parallel-syncs同时同步的从库数量1
quorum客观下线判定所需票数-

启动 Sentinel

# 方式一:使用 redis-sentinel 命令
redis-sentinel /path/to/sentinel.conf

# 方式二:使用 redis-server 的 sentinel 模式
redis-server /path/to/sentinel.conf --sentinel

部署建议

最小部署方案

至少需要 3 个 Sentinel 节点,部署在不同的物理服务器或虚拟机上:

       +----+
| M1 | Master
| S1 | Sentinel 1
+----+
|
+----+ | +----+
| R2 |----+----| R3 | Replica 2 & 3
| S2 | | S3 | Sentinel 2 & 3
+----+ +----+

Configuration: quorum = 2

部署原则

  1. 奇数节点:部署奇数个 Sentinel,便于投票决策
  2. 物理独立:Sentinel 部署在不同的服务器/机架/可用区
  3. 网络稳定:确保 Sentinel 之间、Sentinel 与 Redis 之间网络稳定
  4. 客户端支持:确保客户端库支持 Sentinel

Docker/NAT 环境配置

在 Docker 或 NAT 环境中,需要配置 IP 和端口公告:

# 强制 Sentinel 公告特定 IP 和端口
sentinel announce-ip <外部IP>
sentinel announce-port <外部端口>

Sentinel 命令

查询命令

# 连接 Sentinel
redis-cli -p 26379

# 查看主库信息
127.0.0.1:26379> SENTINEL master mymaster

# 查看从库列表
127.0.0.1:26379> SENTINEL replicas mymaster

# 查看其他 Sentinel
127.0.0.1:26379> SENTINEL sentinels mymaster

# 获取当前主库地址
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"

运维命令

# 检查 Sentinel 配置是否正常
127.0.0.1:26379> SENTINEL CKQUORUM mymaster

# 强制重写配置文件
127.0.0.1:26379> SENTINEL FLUSHCONFIG

# 手动触发故障转移
127.0.0.1:26379> SENTINEL FAILOVER mymaster

# 重置主库状态(慎用)
127.0.0.1:26379> SENTINEL RESET mymaster

动态配置

# 运行时修改配置
127.0.0.1:26379> SENTINEL SET mymaster down-after-milliseconds 5000
127.0.0.1:26379> SENTINEL SET mymaster failover-timeout 60000

# 查看全局配置
127.0.0.1:26379> SENTINEL CONFIG GET down-after-milliseconds

# 修改全局配置(Redis 6.2+)
127.0.0.1:26379> SENTINEL CONFIG SET down-after-milliseconds 5000

客户端集成

Java/Spring Boot 集成

在 Spring Boot 中使用 Sentinel 模式:

# application.yml
spring:
redis:
sentinel:
master: mymaster
nodes: 192.168.1.101:26379,192.168.1.102:26379,192.168.1.103:26379
password: your_password

Python 客户端集成

from redis.sentinel import Sentinel

# 配置 Sentinel 节点
sentinel = Sentinel([
('192.168.1.101', 26379),
('192.168.1.102', 26379),
('192.168.1.103', 26379),
], socket_timeout=0.1)

# 获取主库连接
master = sentinel.master_for('mymaster', socket_timeout=0.1)
master.set('key', 'value')

# 获取从库连接(只读)
slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
value = slave.get('key')

Node.js 客户端集成

const Redis = require('ioredis');

const redis = new Redis({
sentinels: [
{ host: '192.168.1.101', port: 26379 },
{ host: '192.168.1.102', port: 26379 },
{ host: '192.168.1.103', port: 26379 },
],
name: 'mymaster',
password: 'your_password',
});

redis.set('key', 'value');

订阅 Sentinel 事件

Sentinel 通过 Pub/Sub 发布事件通知:

# 订阅所有事件
127.0.0.1:26379> SUBSCRIBE +switch-master
127.0.0.1:26379> SUBSCRIBE +failover-end
127.0.0.1:26379> SUBSCRIBE +sdown
127.0.0.1:26379> SUBSCRIBE +odown

常见事件类型

事件说明
+switch-master主库切换
+sdown主观下线
+odown客观下线
+failover-end故障转移结束
+reboot实例重启
+role-change角色变更

生产环境最佳实践

1. 部署架构

+--------------------+     +--------------------+     +--------------------+
| Server 1 | | Server 2 | | Server 3 |
| +---------------+ | | +---------------+ | | +---------------+ |
| | Redis Master | | | | Redis Replica | | | | Redis Replica | |
| | Sentinel | | | | Sentinel | | | | Sentinel | |
| +---------------+ | | +---------------+ | | +---------------+ |
+--------------------+ +--------------------+ +--------------------+

2. 配置建议

# 推荐配置
port 26379
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

3. 监控要点

  • 监控 Sentinel 进程存活
  • 监控主从复制延迟
  • 监控 Sentinel 日志中的异常事件
  • 定期演练故障转移

4. 常见问题

问题一:故障转移后客户端仍连接旧主库

解决方案:客户端需要实现 Sentinel 支持,自动获取新主库地址。

问题二:网络分区导致脑裂

解决方案:配置 min-replicas-to-writemin-replicas-max-lag

# redis.conf
min-replicas-to-write 1
min-replicas-max-lag 10

问题三:Sentinel 配置不一致

解决方案:使用 SENTINEL FLUSHCONFIG 强制同步配置。

Sentinel vs Redis Cluster

特性SentinelCluster
数据分片不支持支持
高可用支持支持
扩展方式只读扩展读写扩展
配置复杂度
最少节点数36
适用场景中小规模、数据量不大大规模、高并发

选择建议

  • 数据量小(< 单机内存)、需要高可用 → Sentinel
  • 数据量大、需要水平扩展 → Cluster

小结

本章我们学习了:

  1. Sentinel 核心功能:监控、通知、故障转移、配置中心
  2. 故障判定机制:主观下线、客观下线、Quorum 和 Majority
  3. 故障转移流程:选举领头 Sentinel、选举新主库、配置转移
  4. 配置与部署:配置文件详解、部署架构建议
  5. 客户端集成:Java、Python、Node.js 客户端配置
  6. 最佳实践:生产环境部署建议、常见问题解决

练习

  1. 搭建一个 3 节点的 Sentinel 集群
  2. 测试故障转移功能:手动停止 Master 观察切换过程
  3. 使用 Python 客户端连接 Sentinel 并测试自动切换
  4. 订阅 Sentinel 事件,观察故障转移的事件通知

参考资料