概述
Redis从2.8开始正式提供了Redis Sentinel(哨兵)来实现高可用。
Redis Sentinel具有以下几个功能:
- 监控:Sentinel节点会定期检测Redis数据节点、其他Sentinel节点是否可达
- 通知:Sentinel节点会将故障转移结果通知给应用方
- 主节点故障转移:实现从节点晋升为主节点并维护后续正确的主从关系
- 配置提供者:在Redis Sentienl结构中,客户端在初始化时连接的是Sentienl节点集合,从中获取主节点信息
主从复制的问题
Redis主从复制模式是将主节点的数据改变同步给从节点,从节点即可以做备份也可以扩展主节点读能力。
但是主从复制模式存在如下问题:
- 如果主节点故障,需要人工将从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令其他从节点复制新的主节点。
- 主节点的写能力受单机限制
- 主节点的存储能力受到单机限制
Redis Sentinel
当主节点出现故障时,Redis Sentinel能自动完成故障发现和故障转移,并通知应用方,从而实现真正的高可用。
Redis Sentinel是一个分布式架构,其中包含若干个Sentinel节点和Redis数据节点。每个Sentinel节点会对数据节点和其他Sentinel节点进行监控,当发现其他节点不可达时,会对节点做下线标识。如果被标识的是主节点,并且大多数Sentinel节点都认为主节点不可达时,则会选举出一个Sentinel节点来完成自动故障迁移工作,不需要人工干预。Redis Sentinel方案有效解决了Redis的高可用问题。
如下图所示,Redis Sentinel与Redis主从复制模式只是多了若干Sentinel节点并没有针对Redis节点做了特殊处理。
安装部署
下面将以3个Sentinel节点、1个主节点、2个从节点组成一个Redis Sentinel为例进行部署。
物理结构如下表所示:
角色 | ip | port |
---|---|---|
master | 127.0.0.1 | 6379 |
slave-1 | 127.0.0.1 | 6380 |
slave-2 | 127.0.0.1 | 6381 |
sentinel-1 | 127.0.0.1 | 26379 |
sentinel-2 | 127.0.0.1 | 26380 |
sentinel-3 | 127.0.0.1 | 26381 |
部署Redis数据节点
Redis Sentinel中Redis数据节点没有做任何特殊配置,只需正常安装启动。
启动主节点
配置:
1 | redis-6379.conf |
启动主节点:
1 | redis-server redis-6379.conf |
验证:
1 | redis-cli -h 127.0.0.1 -p 6379 ping |
启动从节点
配置1(从节点2配置同理):
1 | redis-6380.conf |
启动从节点:
1 | redis-server redis-6380.conf |
验证:
1 | redis-cli -h 127.0.0.1 -p 6380 ping |
确认主从关系
主节点视角下有两个从节点,分别是127.0.0.1:6380和127.0.0.1:6381
1 | $ redis-cli -h 127.0.0.1 -p 6379 info replication |
从节点的视角,它的主节点是127.0.0.1:6379
1 | $ redis-cli -h 127.0.0.1 -p 6380 info replication |
部署Sentinel节点
配置Sentinel节点
1 | redis-sentinel-26379.conf |
启动Sentinel节点
Sentinel节点的启动方法有两种:
使用redis-sentinel命令:
1
redis-sentinel redis-sentinel-26379.conf
使用redis-server命令加–sentinel参数:
1
redis-server redis-sentinel-26379.conf --sentinel
确认
Sentinel节点本质上是一个特殊的Redis节点,所以也可以通过info命令来查询它的相关信息:
1 | $ redis-cli -h 127.0.0.1 -p 26379 info Sentinel |
从info的Sentinel片段看,Sentinel节点找到了主节点127.0.0.1:6379,发现了它的两个从节点,同时发现Redis Sentinel一共有3个Sentinel节点。
Sentinel API
1 | sentinel masters # 展示所有被监控的主节点状态和统计信息 |
实现原理
Redis Sentinel的基本实现原理,具体包含以下几个方面:
Redis Sentinel的三个定时任务、主观下线和客观下线、Sentinel领导者选举、故障转移。
三个定时任务
Redis Sentinel通过三个定时任务完成对各个节点发现和监控:
- 每隔10秒,每个Sentinel节点会向数据主节点和从节点发送info命令获取最新的拓扑结构,作用有三点:
- 通过向主节点执行info命令,获取从节点信息,所以不需要显示配置从节点
- 有新节点加入时可以立即感知
- 节点不可达或故障转移后,可以通过info命令实时更新节点拓扑信息
- 每隔2秒,每个Sentinel节点会向数据节点的__sentinel__:hello频道发送该节点对于主节点的判断以及当前Sentinel节点的信息,同时每个Sentinel也会订阅此频道,以获取其他Sentinel节点以及它们对主节点的判断。此任务完成以下两个工作:
- 通过订阅主节点__sentinel__:hello频道,获取其他Sentinel节点信息,对于新节点保存信息并建立连接
- Sentinel节点之间交换主节点状态,作为后面客观下线以及领导者选举的依据
- 每隔1秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测确保这些节点可达
主观下线和客观下线
主观下线
Redis Sentinel的第三个定时任务中,每个Sentinel节点会每隔1秒对主节点、从节点、其他Sentinel节点发送ping命令做心跳检测,当这些节点超过down-after-milliseconds没有进行有效回复,Sentinel节点就会对该节点做失败判定,这个行为叫做主观下线。主观下线存在误判的可能。
客观下线
当Sentinel主观下线的节点是主节点时,该Sentinel节点会通过sentinel is-master-down-by-addr命令向其他Sentinel节点询问对主节点的判断,当超过
Sentinel领导者选举
假如Sentinel节点对于主节点已经做了客观下线,接下来Redis会基于Raft算法从Sentinel节点之间会做一个领导者选举的工作,选出一个Sentinel节点作为领导者进行故障转移的工作。
Sentinel节点选举大致思路如下:
- 每个在线的Sentinel节点在做出主节点主观下线时候,会向其他Sentinel节点发送sentinel is-master-down-by-addr命令,要求将自己设置为领导者
- 收到命令的Sentinel节点,如果没有同意过其他Sentinel节点的sentinel is-master-down-by-addr命令,将同意该请求,否则拒绝
- 如果该Sentinel节点发现自己的票数已经大于等于max(quorum, num(sentinels)/2+1),那么它将成为领导者
- 如果此过程没有选举出领导者,将进入下一次选举
故障转移
领导者选举出的Sentinel节点负责故障转移,具体步骤如下:
- 在从节点列表中选出一个节点作为新的主节点,选择方法如下:
- 过滤:“不健康”(主观下线、断线)、5秒内没有回复过Sentinel节点ping响应、与主节点失联超过down-after-milliseconds*10秒
- 选择slave-priority(从节点优先级)最高的从节点列表,如果存在则返回,不存在继续
- 选择复制偏移量最大的从节点,存在返回,不存在继续
- 选择runId最小的节点
- Sentinel领导者节点会对第一步选出来的从节点执行slave no one命令让其成为主节点
- Sentinel领导者节点会向其他从节点发送命令,让它们成为新主节点的从节点,复制规则与parallel-syncs参数有关
- Sentinel节点集合会将原来的主节点更新为从节点,并保持对其关注,当其恢复后命令它去复制新的主节点