一、主从复制存在的问题
一旦主节点出现故障, 需要手动将一个从节点晋升为主节点, 同时需要修改应用方的主节点地址, 还需要命令其他从节点去复制新的主节点, 整个过程都需要人工干预。
二、高可用 redis sentinel
1、概述:
Redis Sentinel是一个分布式架构, 其中包含若干个Sentinel节点和Redis数据节点, 每个Sentinel节点会对数据节点和其余Sentinel节点进行监控, 当它发现节点不可达时, 会对节点做下线标识。 如果被标识的是主节点, 它还会和其他Sentinel节点进行“协商”, 当大多数Sentinel节点都认为主节点不可达时, 它们会选举出一个Sentinel节点来完成自动故障转移的工作, 同时会将这个变化实时通知给Redis应用方。 整个过程完全是自动的, 不需要人工来介入。
它的主要功能有以下几点
- 多个sentinel发现并确认master有问题
- 选举出一个sentinel作为领导
- 选出一个slave作为master
- 通知其余slave成为新的master的slave
- 通知客户端主从变化
- 等待老的master复活成为新的master的slave
2、安装与配置
①配置开启主从节点
7001端口配置,7002类似。
有两个从节点
②配置开启sentinel监控主节点(sentinel是特殊的redis)
配置:
- Sentinel节点的默认端口是26379。
- sentinel monitor mymaster 127.0.0.1 7000 2配置代表sentinel-1节点需要监控127.0.0.1: 7000这个主节点, 2代表判断主节点失败至少需要2个Sentinel节点同意, mymaster是主节点的别名
启动sentinel
redis-sentinel redis-sentinel-26381.conf
当三个Sentinel节点都启动后,拓扑结构图如下:
注意:
- 生产环境中建议Redis Sentinel的所有节点应该分布在不同的物理机上。
- Redis Sentinel中的数据节点和普通的Redis数据节点在配置上没有任何区别, 只不过是添加了一些Sentinel节点对它们进行监控。
三、redis-sentinel实现原理
1、sentinel 集群通过三个定时监控任务完成对各个节点发现和监控。
1、每10秒每个sentinel对master和slave执行info
- 发现slave节点
- 确认主从关系
作用:
sentinel 集群可以得知 master 和 slave 的基本信息,①通过向主节点执行 info 命令,获取从节点的信息,所以 sentinel 节点不需要显式配置监控从节点,②当有新的从节点加入时都可以立刻感知出来,③当 master 节点故障或者故障转移后,可以通过 info 命令实时更新 redis 主从信息。
2、 每隔2秒,每个 sentinel 节点会向 redis 数据节点的
__sentinel__:hello
这个channel(频道)发送一条消息。每个sentinel都会订阅该频道。信息交互平台:信息交换、领导者选举该定时任务的作用:
- 发现新的 sentinel节点:通过订阅主节点的
__sentinel__:hello
了解其他的 sentinel 节点信息,如果是新加入的 sentinel 节点,将该 sentinel 节点信息保存起来,并与该 sentinel 节点创建连接。- sentinel 节点之间交换主节点的状态,用做 master 下线和故障处理的 leader 选举的依据。
3、每隔1秒, 每个Sentinel节点会向主节点、 从节点、 其余Sentinel节点发送一条ping命令做一次心跳检测, 来确认这些节点当前是否可达。
通过定时发送ping命令,sentinel 节点对主节点、从节点、其余 sentinel 节点都建立起连接,实现了对每个节点的监控,这个定时任务是节点下线判定的重要依据。
2、主观下线和客观下线
sentinel monitor mymaster 127.0.0.1 6379 2
master名 法定人数<quorum> 建议节点数/2+1,超过50%。让我想起了区块链
sentinel down-after-milliseconds mymaster 30000 #超时下线
master名 30s
sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid> #问一下别的sentinel是否master该下线了
1、主观下线
每个 sentinel 节点每隔1秒对主节点、从节点、其他 sentinel 节点发送 ping 命令做心跳检测,当这些节点超过
down-after-milliseconds
没有进行有效回复,sentinel节点就会认为该节点下线,这个行为叫做主观下线。主观下线是某个 sentinel 节点的判断,并不是 sentinel 集群的判断,所以存在误判的可能。
2、客观下线
当 sentinel 主观下线的节点是主节点时,该 sentinel 节点会通过
sentinel ismaster-down-by-addr
命令向其他 sentinel 节点询问对主节点的判断,当超过<quorum>个(quorum可配置)sentinel 节点认为主节点有问题,这时该 sentinel 节点会做出客观下线的决定,也就是大部分(超过50%)是 sentinel 节点都对主节点的下线做了同意的判定,那么这个判定就是客观的。sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid> ·ip: 主节点IP。 ·port: 主节点端口。 ·current_epoch: 当前配置纪元。 ·runid: 此参数有两种类型, 不同类型决定了此API作用的不同。 当runid等于“*”时, 作用是Sentinel节点直接交换对主节点下线的判定。 当runid等于当前Sentinel节点的runid时, 作用是当前Sentinel节点希望目标Sentinel节点同意自己成为领 导者的请求, 有关Sentinel领导者选举, 后面会进行介绍。
如果发送:sentinel is-master-down-by-addr 127.0.0.1 6379 0 *
返回三个参数:
- down_state: 目标Sentinel节点对于主节点的下线判断, 1是下线, 0是在线。
- leader_runid: 当leader_runid等于“*”时, 代表返回结果是用来做主节点是否不可达, 当leader_runid等于具体的runid, 代表目标节点同意runid成为领导者。
- leader_epoch: 领导者纪元。
3、故障转移前的领导者节点选举
当 sentinel 集群确认 master 下线,需要选举出一个 leader 节点来进行故障转移
选举:通过sentinel is-master-down-by-addr命令都希望成为领导者
- 每个做主观下线的Sentinel节点向其他Sentinel节点发送命令,要求将它设置为领导者。
- 收到命令的Sentinel节点如果没有同意通过其他Sentinel节点发送的命令,那么将同意该请求,否则拒绝。
- 如果该Sentinel节点发现自己的票数已经超过Sentinel集合半数且超过quorum ,那么它将成为领导者。
- 如果此过程有多个Sentinel节点成为了领导者,那么将等待一段时间重新进行选举。
4、故障转移(sentinel领导者节点做)
1、从slave节点中选取一个“合适的”节点作为新的master节点。
- 选择slave-priority(优先级)最高的slave节点,如果存在则返回,不存在则继续。
- 选择复制偏移量最大的slave节点,如果存在则返回,不存在则继续。
- 选择runid最小的slave节点。
2、对上面的slave执行slave no one命令让它成为master节点。
3、向剩余的slave节点发送命令,让它们成为新的master的slave节点。复制master节点。
4、更新原来的master为slave,并一直“关注”,当它恢复后,命令它去复制新的master节点。
四、读写分离
从节点也可以用来扩展主节点的读能力,尤其是在读多写少的场景下。
但是存在一个问题:从节点不是高可用的,如果从节点出现故障,与其相连的客户端获取不到服务。其次,主节点没有客观下线,客观下线只针对主节点。
方法:
在设计Redis Sentinel的从节点高可用时, 只要能够实时掌握所有从节点的状态(可以依赖Sentinel节点的消息通
知, 获取Redis数据节点的状态变化), 把所有从节点看做一个资源池 , 无论是上线还是下线从节点, 客户端都能及时感知到(将其从资源池中添加或者删除) , 这样从节点的高可用目标就达到了。![]()
读写分离架构图