五、哨兵
5.1 基本概念
主从复制解决了数据冗余与读写分离,但主节点宕机后仍需要人工切换,哨兵是一组独立进程,负责监控数据节点、通知状态变化,并在主节点故障时自动完成故障转移。
分布式是指 Redis 数据节点、哨兵节点与客户端分布在多个物理节点上,与后文的 Redis Cluster 是两回事。
哨兵节点集合建议保持奇数。
哨兵定期监控所有节点,主节点故障时的转移流程大致分四步:
主节点故障,从节点同步连接中断,主从复制停止
哨兵通过定期监控发现主节点故障,与其他哨兵协商,达成多数认同的共识——这一步可以排除“故障的是发现故障的哨兵节点”这类误判
哨兵之间用 Raft 算法选举出一个领导节点,由其负责后续转移
领导节点从从节点中选出新主节点,让其他从节点同步新主节点,并通知应用层切换
5.2 主观下线与客观下线
下线判定分两个阶段。哨兵在指定时间内没有收到主节点心跳,先判定为主观下线;随后哨兵节点之间互相协商投票,当故障得票数达到配置的法定票数,触发客观下线:
# sentinel.conf 中监控主节点,最后的 2 是法定票数 sentinel monitor redis-master 172.22.0.4 6379 2法定票数决定了“主节点故障”这一结论需要多少哨兵认可才算做实。
5.3 选举原理
选出负责转移的 leader 用到 Raft 算法,核心逻辑可以概括为“先下手为强”:
每个哨兵向其他所有哨兵发起拉票请求
收到请求的节点回复投票响应
一轮投票结束后,得票过半的节点自动成为 leader
出现平票时重新再投一次
这也是哨兵节点建议配置奇数个的原因:偶数个节点会增平票概率,带来不必要的开销。
决定谁能率先拉票的因素是网络延时,本身就带有随机性。
5.4 部署示例
基于 docker 可以快速搭建一主两从加三个哨兵的实验环境。
docker-compose 中为每个节点声明服务与端口映射,哨兵通过 sentinel monitor 配置监控主节点地址,容器内部使用虚拟 IP 相互通信:
services: redis-master: image: redis:5.0.9 command: redis-server --port 6379 redis-slave-1: image: redis:5.0.9 command: redis-server --slaveof redis-master 6379 --port 6379 redis-sentinel-1: image: redis:5.0.9 command: redis-sentinel /usr/local/etc/redis/sentinel.conf --port 26379哨兵启动日志会输出投票与切换过程,主节点故障后可以看到 +switch-master 记录,标识主节点从旧地址切换到了新地址,从节点随之重新挂载: