1. 哨兵模式简介
在Redis主从复制的集群体系中, 如果 master宕机, 需要手动将一个从节点晋升为主节点,需要将其他节点的主节点替换为新的主节点,同时还需要修改应用的主节点地址 整个过程都需要人工干预 ,
在 Redis 2.8 提供比较完善的解决方案:Redis Sentinel
在所有的slave中,将自动竞选出一个master来提供服务,具体流程如下
- 关闭master和所有slave 对外提供服务
- 找一个slave作为master
- 修改其他slave的配置,连接新的主
- 启动新的master与slave
- 全量复制N+部分复制N
在上述流程中,有几个问题:
- 谁来监控整个Redis集群体系,master挂了谁知道
- 关闭竞选期间的数据服务谁来承接?
- 找一个主?怎么找法?
- 修改配置后,原始的master恢复了怎么办?
答案为, 由"哨兵"提供解决方案
哨兵(sentinel) 是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的 master并将所有slave连接到新的master。
哨兵的作用 :
-
监控
不断的检查master和slave是否正常运行。 master存活检测、master与slave运行情况检测
-
通知(提醒)
当被监控的服务器出现问题时,向其他(哨兵间,客户端)发送通知。
-
自动故障转移
断开master与slave连接,选取一个slave作为master,将其他slave连接到新的master,并告知客户端新的服 务器地址
注意: 哨兵也是一台redis服务器,只是不提供数据服务 通常哨兵配置数量为单数
架构图:
2. 启用哨兵模式
模拟如下:
Redis集群配置一master 二slave的主从结构
配置三个哨兵,哨兵相关配置,配置在sentinel.conf文件中
启动哨兵 :redis-sentinel sentinel-端口号.conf
,使用 redis-sentinel 命令启动,并指定配置文件
sentinel配置文件如下:
三个哨兵的配置文件主要信息如下,都是一样的,若在同电脑上启动,只需换个端口号即可,创建三份配置文件,启动时指定对应的sentinel配置文件:
// 哨兵端口号
port 26379
//数据目录
dir /data
// 指定此哨兵监听的master主机的ip和端口,命令为mymaster, 并指定判断宕机的定义为2(通常为哨兵数量的一半+1)
//即当有两个哨兵认定此master宕机时,即进行选举
sentinel monitor mymaster 127.0.0.1 6379 2
//此哨兵认定指定master 为宕机的条件, 本例为30秒没有响应
sentinel down-after-milliseconds mymaster 30000
//出新的master时,slave并发同时进行同步的 个数
sentinel parallel-syncs mymaster 1
//认定在同步过程中,多久时间为超时, 180秒
sentinel failover-timeout mymaster 180000
启动流程:
启动 master和两个slave,
再依次使用 redis-sentinel
指令启动三个 哨兵,监控集群的运行情况,并且三个哨兵互相之间也保持联系,
若此时关闭master, 待30秒后,将在slave中推举出新的master
3.工作原理
监控阶段
sentinel在大部分的时间,都是处于对集群中每个 节点的监控阶段,那么 sentinel又是怎么进行监控的呢
- 当sentinel连接master时, 会通过info指令,获取到master的详细信息,runid ,role:master ,各个slave的信息等, master也会保存此sentinel的信息,后续每隔10s 都会发送一次,更新master的信息和获取可能的新的 slave节点
- 再根据获取到的slave节点的地址信息, 发送info指令,获取到各个slave的详细信息,runid, offset 等
- 当有另外一个 sentinel 连接master时,重复上面的工作,获取各个节点的信息,同时也获取到了 master保存的其他sentinel的信息,并通过此地址信息,与另外的sentinel 建立 发布/订阅的通道,进行传输消息, 并通过ping命令来确保对方的存活
- 再有新的sentinel 也是如此,各个sentinel 保持互相通信
示意图如下:
通知阶段
在sentinel运行期间,需要 定期的向每个节点询问健康状态, 此时由一个sentinel询问,并将结果传播给每个sentinel,下次时可能就为另一个
示意图如下:
故障转移阶段
当sentinel1 不断向master进行监控,而超时时(自定义配置), 标记master的flags为SRI_S_DOWN
,
此时若是sentinel自己的网络问题, 将无法将消息通知给其他sentinel,若不是,将此消息推送给其他sentinel
此时吃瓜群众sentinel1和sentinel2,也跑去进行询问,也都超过了配置的超时时间,并标记flags,
若标记的个数大于哨兵个数的一半(自定义配置), 将标记master的flags为SRI_O_DOWN
,此时正式确定此master真的挂了
示意图如下:
Sentine选举:
此时若master已经被标记为客观下线, 还需要一个Sentinel 节点来完成故障转移,
所以会有一个选举的过程,在所有sentinel中选举出故障转移工作者。
Redis 节点采用 Raft 算法来完成领导者写选举,下面主要介绍 Sentinel 选举的主要流程。
- 每一个标记主观下线的 Sentinel 节点都参与投票,并且自己也是投票者,他们会向其他 Sentinel 节点发送
sentinel is-master-down-by-addr
,携带 挂机master的ip端口,竞选次数,自己的runid等等信息, 要求接受者选举自己为执行者 - Sentinel 节点会同意首次发送给自己信息的其他sentinel并拒绝后来者
- 如果当有 Sentinel 节点发现自己得到的票数已经超过半数 ,那么他将成为执行者
- 若一轮下来,结果有多个执行者,则重复上述过程,知道选举出一个sentinel为止
例如,此时有ABC 四个sentinel, A率先完成客观下线,并收到信息, 并向其他BC 发送信息,BC 都是首次接收,所以投票给A,此时 B也完成了客观下线, 也发送信息给AC, 但是C已经投过了,只有A投了一票, 当C完成时,将一票都没有,所以此时A为执行者,一般来说哨兵选择的过程很快,谁先完成客观下线,一般就能成为领导者
故障转移执行
Sentinel 节点通过选举成为了执行者,其具体步骤如下:
- 从从节点列表中选择一个节点作为新的主节点,选择的策略如下:
- 过滤掉所有不健康的节点, 即在线的, 和响应快的
- 再过滤与原master连接比较慢的,
- 后面则按照优先级最高的, offset最大的,数据最完整, runid最小的 依次选举出slave
- 在新的主节点上执行
slaveof no one
,让其变成主节点 - 向剩余的从节点发送命令,让它们成为新主节点的从节点