Redis集群选举原理与脑裂问题

系列文章目录

第一节 Redis的安装
第二节 Redis的五种数据结构(String、Hash、List、Set、ZSet)
第三节 Redis的持久化方式
第四节 Redis主从架构
第五节 Redis哨兵高可用架构
第六节 Redis集群高可用架构



一、Redis集群选举原理

当slave节点发现自己的master节点变为FAIL状态时,便尝试进行Failover(故障转移),以期成为新的master。由于挂掉的master节点可能会有多个slave节点,从而存在多个slave节点竞争成为master节点的过程。
过程如下:

  1. slave节点发现自己的master节点变为FAIL状态
  2. 将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST(会携带有currentEpoch)信息
  3. 其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch(纪元)只发送一次ACK
  4. 尝试Failover的slave收集master返回的FAILOVER_AUTH_ACK
  5. slave收到超过半数master的ACK后变成新Master(这里解释了集群为什么至少需要三个主节点,如果只有两个,当其中一个挂了,只剩一个主节点是不能选举成功的)
  6. slave广播Pong消息通知其他集群节点

从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,一定的延迟确保我们等待FAIL状态在集群中传播,slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票

  • 延迟计算公式:DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms
  • SLAVE_RANK表示此slave已经从master复制数据的总量的rank。Rank越小代表已复制的数据越新。这种方式下,持有最新数据的slave将会首先发起选举(理论上)。

currentEpoch的含义

  1. 这是一个集群状态相关的概念,可以用来记录集群状态变更的递增版本号。
  2. 每个集群节点,都会通过 server.cluster->currentEpoch 记录当前的 currentEpoch。
  3. 集群节点创建时,不管是master还是slave,都将currentEpoch置为 0。
  4. 当前节点接收到来自其他节点的包时,如果发送者的currentEpoch(消息头部会包含发送者的currentEpoch)大于当前节点的currentEpoch,那么当前节点会更新 currentEpoch 为发送者的
    currentEpoch。
  5. 集群中所有节点的 currentEpoch 最终会达成一致,相当于对集群状态的认知达成了一致。

currentEpoch的作用

当集群的状态发生改变,目前currentEpoch只用于slave的故障转移流程,例如当 slave1节点发现其所属的master节点无法访问时,就会试图发起故障转移流程。

  1. 增加 currentEpoch的值,这个增加后的 currentEpoch 是所有集群节点中最大的。
  2. 然后slave1向所有节点发起拉票请求,请求其他master投票给自己,使自己能成为新的master。
  3. 其他节点收到包后,发现发送者的 currentEpoch 比自己的 currentEpoch 大,就会更新自己的
    currentEpoch,并在尚未投票的情况下,投票给slave1,表示同意使其成为新的master。

二、集群脑裂问题

redis集群没有过半机制会有脑裂问题,网络抖动导致脑裂后多个主节点对外提供写服务,一旦网络环境问题恢复,会将其中一个主节点变为从节点,然后从节点会从主节点进行全量数据复制,这时主节点变成从节点前的所有数据丢失。
规避方法可以在redis配置里加上参数(这种方法不可能百分百避免数据丢失,参考集群leader选举机制):

min-replicas-to-write 1  //写数据成功最少同步的slave数量,这个数量可以模仿大于半数机制配置,比如集群总共三个节点可以配置1,加上leader就是2,超过了半数

注意:这个配置在一定程度上会影响集群的可用性,比如slave要是少于1个,也就是当只有master节点时,这个集群也不能提供服务了,需要具体场景权衡选择。

三、其它问题

1、集群是否完整才能对外提供服务

当redis.conf的配置cluster-require-full-coverage为no时,表示当负责一个插槽的master主库下线且没有相应的slave从库进行故障恢复时,集群仍然可用,如果为yes则集群不可用。

2、Redis集群为什么至少需要三个master节点,并且推荐节点数为奇数?

因为新master的选举需要大于半数的集群master节点同意才能选举成功,如果只有两个master节点,当其中一个挂了,无法达不到选举新master的条件的。
奇数个master节点可以在满足选举该条件的基础上节省一个节点,比如三个master节点和四个master节点的集群相比,大家如果都挂了一个master节点都能选举新master节点,如果都挂了两个master节点都没法选举新master节点了,所以奇数的master节点更多的是从节省机器资源角度出发说的。

3、Redis集群对批量操作命令的支持

对于类似mset,mget这样的多个key的原生批量操作命令,redis集群只支持所有key落在同一slot的情况,如果有多个key一定要用mset命令在redis集群上操作,则可以在key的前面加上{XX},这样参数数据分片hash计算的只会是大括号里的值,这样能确保不同的key能落到同一slot里去,示例如下:

mset {student1}:1001:name zhangsang {student1}:1001:age 20

假设name和age计算的hash slot值不一样,但是这条命令在集群下执行,redis只会用大括号里的 student1做hash slot计算,所以算出来的slot值肯定相同,最后都能落在同一slot。


  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值