5.2 Sentinel (哨兵) (Redis 2.8+) 5.2 Redis Sentinel (哨兵) (Redis 2.8+) 详解与实践 在构建高可用 Redis 集群时,主从复制(Replication)是基础。然而,单纯的主从复制架构存在一个明显的单点故障风险:当主节点(Master)发生故障时,需要人工介入进行故障转移,这会导致服务中断,且恢复时间较长。为了解决这个问题,Redis 2.8 版本引入了 Sentinel (哨兵) 系统。 Sentinel 的核心作用是监控、通知和自动故障转移。它可以监控 Redis 主节点和从节点的状态,当主节点出现故障时,自动将一个从节点晋升为新的主节点,并通知客户端更新连接信息,从而实现 Redis 集群的高可用性。 5.2.
在构建高可用 Redis 集群时,主从复制(Replication)是基础。然而,单纯的主从复制架构存在一个明显的单点故障风险:当主节点(Master)发生故障时,需要人工介入进行故障转移,这会导致服务中断,且恢复时间较长。为了解决这个问题,Redis 2.8 版本引入了 Sentinel (哨兵) 系统。
Sentinel 的核心作用是监控、通知和自动故障转移。它可以监控 Redis 主节点和从节点的状态,当主节点出现故障时,自动将一个从节点晋升为新的主节点,并通知客户端更新连接信息,从而实现 Redis 集群的高可用性。
一个完整的 Sentinel 系统通常由多个 Sentinel 实例组成,它们协同工作,共同监控 Redis 集群。Sentinel 的主要组件和工作原理如下:
1. 监控 (Monitoring):
监控目标: Sentinel 会定期检查 Redis 主节点和从节点的健康状态。监控的内容包括:
主观下线 (Subjective Down, SDOWN): 当 Sentinel 无法在 down-after-milliseconds 时间内连通 Redis 实例(主节点或从节点)时,会将其标记为 主观下线。
客观下线 (Objective Down, ODOWN): 当足够数量的 Sentinel 实例(达到 quorum 仲裁值)都认为同一个主节点 主观下线 时,该主节点才会被标记为 客观下线。客观下线是触发故障转移的条件。
监控机制: Sentinel 通过定期向 Redis 实例发送 PING 命令来检测其健康状态。同时,Sentinel 还会订阅 Redis 实例的 +switch-master 和 +slave 等频道,以获取拓扑变化信息。
2. 通知 (Notification):
事件通知: Sentinel 会将监控到的事件(例如主观下线、客观下线、故障转移、新的主节点选举等)通知给:
其他 Sentinel 实例: Sentinel 之间通过 Redis 的发布/订阅机制进行通信,共享监控信息和状态。
客户端: Sentinel 提供发布/订阅频道,客户端可以订阅这些频道,实时获取 Redis 集群的状态变化,并据此调整连接策略。
3. 故障转移 (Failover):
触发条件: 当主节点被 Sentinel 集群判定为 客观下线 时,故障转移过程会被触发。
故障转移流程:
选举 Leader Sentinel: 多个 Sentinel 实例会进行 Leader 选举,选出一个 Leader Sentinel 负责执行故障转移。选举过程基于 Raft 算法的简化版本,确保只有一个 Sentinel 实例执行故障转移操作。
选择新的主节点: Leader Sentinel 会从当前主节点的所有从节点中选择一个合适的从节点晋升为新的主节点。选择策略通常基于以下因素:
优先级 (slave-priority): 优先级高的从节点优先被选择。
复制偏移量 (replication offset): 复制偏移量最新的从节点(数据同步最完整)优先被选择。
Run ID: Run ID 较小的从节点(启动时间较早)优先被选择。
晋升从节点为主节点: Leader Sentinel 会向选定的从节点发送 SLAVEOF NO ONE 命令,将其晋升为新的主节点。
重配置其他从节点: Leader Sentinel 会命令其他从节点复制新的主节点。
通知客户端和更新配置: Leader Sentinel 会通知客户端新的主节点地址,并更新 Sentinel 集群自身的配置信息。
恢复旧主节点 (可选): 当旧的主节点恢复后,Sentinel 会将其降级为新的主节点的从节点。
4. 配置提供者 (Configuration Provider):
Sentinel 作为客户端的配置提供者,客户端不再直接连接固定的 Redis 主节点,而是连接 Sentinel 集群。
客户端通过 Sentinel 查询当前可用的主节点地址,并根据 Sentinel 的通知动态更新连接信息。
总结 Sentinel 的关键特性:
高可用性: 自动故障转移保证 Redis 集群在主节点故障时仍能对外提供服务。
监控和通知: 实时监控 Redis 实例状态,及时通知客户端和管理员。
配置管理: 客户端通过 Sentinel 获取动态的 Redis 集群配置信息,简化客户端连接管理。
去中心化: Sentinel 集群本身是去中心化的,多个 Sentinel 实例共同工作,提高系统的健壮性。
接下来,我们通过代码实践来演示如何配置和部署 Redis Sentinel 系统。
环境准备:
三台服务器 (或虚拟机): 用于部署 Redis 主节点、从节点和 Sentinel 实例。
Redis 版本: Redis 2.8 或更高版本。
部署架构 (示例):
Server 1 (192.168.1.101): Redis Master (端口 6379)
Server 2 (192.168.1.102): Redis Slave (端口 6380)
Server 3 (192.168.1.103): Sentinel 1 (端口 26379), Sentinel 2 (端口 26380), Sentinel 3 (端口 26381)
步骤 1: 配置 Redis 主从复制
在 Server 1 (Master) 上: 无需特殊配置,默认即可作为 Master。
在 Server 2 (Slave) 上: 修改 redis.conf 文件:
port 6380 slaveof 192.168.1.101 6379 masterauth your_redis_password # 如果 Master 设置了密码 requirepass your_redis_password # 如果 Slave 也需要密码
port 6380: 指定 Slave 的端口为 6380。
slaveof 192.168.1.101 6379: 指定 Master 的 IP 和端口。
masterauth your_redis_password: 如果 Master 设置了密码,需要配置此项。
requirepass your_redis_password: 如果 Slave 也需要密码保护,配置此项 (可选,建议与 Master 保持一致)。
启动 Redis Master 和 Slave:
redis-server /path/to/redis.conf # Server 1 redis-server /path/to/redis.conf # Server 2 (修改后的 redis.conf)
验证主从复制是否正常工作,可以在 Master 上执行 INFO replication 命令,查看 Slave 信息。
步骤 2: 配置 Sentinel 实例
在 Server 3 (Sentinel) 上: 创建 Sentinel 配置文件 sentinel.conf (可以复制 redis.conf 并进行修改):
port 26379 # Sentinel 端口 sentinel monitor mymaster 192.168.1.101 6379 2 # 监控 Master sentinel down-after-milliseconds mymaster 5000 # 5 秒未响应判定 SDOWN sentinel failover-timeout mymaster 60000 # 故障转移超时时间 60 秒 sentinel parallel-syncs mymaster 1 # 故障转移后,每次只允许一个 Slave 同步 sentinel auth-pass mymaster your_redis_password # 如果 Master 设置了密码 # 可选配置 (根据需要配置) # sentinel notification-script mymaster /path/to/notification.sh # 事件通知脚本 # sentinel client-reconfig-script mymaster /path/to/client-reconfig.sh # 客户端重配置脚本
port 26379: Sentinel 实例的端口。
sentinel monitor mymaster 192.168.1.101 6379 2: 核心配置,定义 Sentinel 监控的 Master 集群。
mymaster: Master 集群的名称 (可以自定义)。
192.168.1.101 6379: Master 的 IP 和端口。
2: quorum 仲裁值,至少需要 2 个 Sentinel 实例同意才能判定 Master 客观下线。
sentinel down-after-milliseconds mymaster 5000: Sentinel 向 Master 或 Slave 发送 PING 命令后,如果 5000 毫秒内没有收到有效回复,则判定为 主观下线 (SDOWN)。
sentinel failover-timeout mymaster 60000: 故障转移的超时时间,单位毫秒。
sentinel parallel-syncs mymaster 1: 在故障转移后,新的 Master 与 Slave 进行数据同步时,允许并行同步的 Slave 数量。设置为 1 表示每次只允许一个 Slave 进行同步,可以降低 Master 的负载。
sentinel auth-pass mymaster your_redis_password: 如果 Master 需要密码验证,Sentinel 需要配置此项才能连接 Master。
sentinel notification-script 和 sentinel client-reconfig-script: 可选配置,用于配置事件通知脚本和客户端重配置脚本,可以实现更高级的功能,例如发送告警邮件、自动更新客户端连接配置等。
启动 Sentinel 实例 (在 Server 3 上启动三个 Sentinel 实例):
redis-sentinel /path/to/sentinel.conf # Sentinel 1 (端口 26379) redis-sentinel /path/to/sentinel.conf --port 26380 # Sentinel 2 (端口 26380) redis-sentinel /path/to/sentinel.conf --port 26381 # Sentinel 3 (端口 26381)
注意:启动第二个和第三个 Sentinel 实例时,需要使用 --port 参数指定不同的端口,并确保配置文件中 port 配置与启动参数一致。
步骤 3: 验证 Sentinel 工作状态
使用 redis-cli 连接 Sentinel:
redis-cli -h 192.168.1.103 -p 26379
执行 Sentinel 命令查看状态:
SENTINEL MASTERS: 查看 Sentinel 监控的所有 Master 集群信息。
SENTINEL MASTER mymaster: 查看指定 Master 集群 mymaster 的详细信息。
SENTINEL SLAVES mymaster: 查看 mymaster 集群的所有 Slave 信息。
SENTINEL SENTINELS mymaster: 查看监控 mymaster 集群的所有 Sentinel 实例信息。
例如,执行 SENTINEL MASTER mymaster 命令,可以看到类似以下输出:
127.0.0.1:26379> sentinel master mymaster 1. name "mymaster" 2. ip "192.168.1.101" 3. port "6379" 4. runid "8baf8c34e07c01d1f876475d926d9b7e1a2b3c4d" 5. flags "master" 6. pending-commands "0" 7. last-ping-sent "0" 8. last-ok-ping-reply "738" 9. last-ping-reply "738" 10. down-after-milliseconds "5000" 11. info-refresh "182" 12. role-reported "master" 13. role-reported-time "678742" 14. config-epoch "1" 15. num-slaves "1" 16. num-sentinels "3" 17. quorum "2" 18. failover-timeout "60000" 19. parallel-syncs "1" 20. auth-pass "<password>" 21. current-epoch "1" 22. last-vote "0" 23. last-failover "0" 24. failover-in-progress "0"
步骤 4: 模拟故障转移
手动停止 Master 节点 (Server 1):
redis-cli -h 192.168.1.101 -p 6379 SHUTDOWN
观察 Sentinel 日志 (Server 3): Sentinel 会检测到 Master 下线,并开始进行故障转移。日志中会显示 Leader 选举、选择新的 Master、晋升 Slave 等过程。
验证新的 Master (Server 2): 在故障转移完成后,Server 2 (192.168.1.102) 上的 Redis 实例会被晋升为新的 Master。可以通过 redis-cli -h 192.168.1.102 -p 6380 INFO replication 命令查看其角色已变为 role:master。
验证 Slave (原 Master 节点恢复后): 当 Server 1 上的原 Master 节点重新启动后,它会被 Sentinel 自动降级为新的 Master (Server 2) 的 Slave。可以通过 redis-cli -h 192.168.1.101 -p 6379 INFO replication 命令查看其角色已变为 role:slave,并且 master_host 和 master_port 指向新的 Master。
步骤 5: 客户端连接 Sentinel
客户端连接方式: 客户端不再直接连接固定的 Master 地址,而是连接 Sentinel 集群。
获取 Master 地址: 客户端需要使用支持 Sentinel 的 Redis 客户端库,通过 Sentinel 提供的 API 获取当前可用的 Master 地址。
示例 (Python redis-py 客户端库):
from redis.sentinel import Sentinel # Sentinel 集群地址 sentinel = Sentinel([('192.168.1.103', 26379), ('192.168.1.103', 26380), ('192.168.1.103', 26381)], socket_timeout=0.1) # 获取 Master 连接 master = sentinel.master_for('mymaster', socket_timeout=0.1) # 执行 Redis 命令 master.set('foo', 'bar') print(master.get('foo')) # 获取 Slave 连接 (只读连接,可选) slave = sentinel.slave_for('mymaster', socket_timeout=0.1) print(slave.get('foo'))
客户端通过 Sentinel() 初始化 Sentinel 连接对象,传入 Sentinel 集群的地址列表。
sentinel.master_for('mymaster') 方法获取名为 mymaster 的 Master 集群的连接。
sentinel.slave_for('mymaster') 方法获取 mymaster 集群的 Slave 连接 (只读)。
当 Master 发生故障转移后,客户端库会自动从 Sentinel 获取新的 Master 地址,并重新建立连接,实现透明的故障转移。
1. quorum 仲裁值:
sentinel monitor mymaster <master-ip> <master-port> <quorum> 中的 <quorum> 参数决定了判定 Master 客观下线所需的 Sentinel 数量。
最佳实践: quorum 值通常设置为 (sentinel_instances / 2) + 1,确保在大多数 Sentinel 实例都正常工作的情况下才能进行故障转移,避免脑裂问题。例如,3 个 Sentinel 实例,quorum 设置为 2 或 3 都是合理的。
2. down-after-milliseconds 参数:
sentinel down-after-milliseconds mymaster <milliseconds> 设置 Sentinel 判定 Master 或 Slave 主观下线的超时时间。
最佳实践: 根据网络环境和业务需求调整,一般设置为几秒到十几秒。如果网络不稳定,可以适当增加该值,避免误判。
3. failover-timeout 参数:
sentinel failover-timeout mymaster <milliseconds> 设置故障转移的超时时间。
最佳实践: 需要根据业务对故障转移时间的要求进行调整。如果对故障转移时间要求较高,可以适当减小该值,但也要考虑故障转移过程的复杂性,避免设置过小导致故障转移失败。
4. parallel-syncs 参数:
sentinel parallel-syncs mymaster <num> 设置故障转移后,新的 Master 与 Slave 进行数据同步时,允许并行同步的 Slave 数量。
最佳实践: 根据 Master 的负载能力和 Slave 的数量进行调整。如果 Slave 数量较多,可以适当增加该值,加快同步速度,但也要注意 Master 的负载。
5. Sentinel 实例数量:
6. 安全配置:
密码保护: 为 Redis Master 和 Slave 设置密码,并在 Sentinel 配置中配置 sentinel auth-pass 参数。
网络隔离: Sentinel 实例和 Redis 实例部署在安全的网络环境中,避免外部访问。
7. 监控与告警:
局限性:
配置复杂性: Sentinel 的配置相对主从复制较为复杂,需要理解各个参数的含义和作用。
故障转移时间: 故障转移需要一定的时间,虽然 Sentinel 可以自动进行故障转移,但仍然会有短暂的服务中断。
脑裂风险 (理论上): 在极端网络分区情况下,理论上可能出现脑裂问题,但通过合理的 quorum 配置和网络规划可以大大降低风险。
替代方案:
Redis Cluster: Redis Cluster 是 Redis 官方提供的分布式解决方案,它将数据分片存储在多个节点上,并内置了高可用和自动故障转移机制。Redis Cluster 相比 Sentinel 更为复杂,但提供了更高的性能和可扩展性。
第三方 Redis 高可用方案: 例如 Twemproxy + Redis, Codis 等,这些方案在某些特定场景下可能更适用。
选择建议:
对于中小规模应用,对数据一致性要求不高,且希望简单易用: Sentinel 是一个不错的选择。
对于大规模应用,对性能和可扩展性要求较高,且需要更强大的高可用性保障: Redis Cluster 是更合适的选择。
对于需要定制化高可用方案的场景: 可以考虑第三方 Redis 高可用方案。
Redis Sentinel 是构建高可用 Redis 集群的重要组件,它通过监控、通知和自动故障转移机制,有效地解决了主从复制架构中的单点故障问题,提高了 Redis 服务的可用性和稳定性。
在实际应用中,需要根据具体的业务需求和场景,合理配置 Sentinel 参数,并结合监控告警系统,确保 Redis 集群的稳定运行。同时,也需要了解 Sentinel 的局限性,并根据需要考虑更高级的 Redis Cluster 或其他高可用方案。