Redis故障转移

概述

本文主要讲述了Redis故障转移的原理及过程,可与「Redis高可用架构」文章一同阅读,可更好理解相关内容,及整个Redis高可用架构的实现原理。

Leader 选举

哨兵首先进入 WATI_START 状态进行准备,等待哨兵成为哨兵集群的 Leader 才有资格进行故障转移。如果在超时时间之内哨兵都没有成为 Leader,则哨兵会调用 sentinelAbortFailover() 函数并结束本次故障转移。

当哨兵想要进行故障转移,首先需要得到多数哨兵的支持才能进行。而且,同一时间可能会有多个哨兵发起故障转移,所以故障转移前需要进行一轮竞选,得到多数选票的哨兵会被称为 Leader,只有 Leader 才能进行故障转移。

选举原理

Redis 的 Leader 选举使用的是 Raft 算法,因此 Leader 选举的流程是相同的,具体可见:【分布式】Raft 算法 - Leader 选举

哨兵属性

根据 Raft 算法,每个哨兵需要存储两个信息,是当前任期心仪候选人 ,在 Redis 定义为 current_epochleaderleander 字段用于存储心仪候选人的 runId

投票请求

同时,哨兵的投票请求依旧沿用 SENTINEL is-master-down-by-addr 指令,但此时除了附上自己的 Epoch 之外,还会在参数中带上自己的 runId,标志投票的发起人。如:

复制代码
SENTINEL is-master-down-by-addr 172.26.0.101 6379 4 9effe0cdc338e245391055caa45a05adf61fed37

投票方法

根据 Raft 算法,哨兵的投票原则就是:leader 字段是谁的 ID,就投给谁

  1. 当哨兵要参加竞选,就会将自己的 current_epoch 字段加一,并将 leader 字段指向自己。
  2. 当哨兵接收到投票请求,如果请求的 epoch 小于等于哨兵自身的 current_epoch,就投给自己 leader 字段所指的哨兵。如果大于自身的 current_epoch,就将更新自己的 leader 字段为请求中的 runId,再将票投给对方。
  3. 根据第一点和第二点,如果竞选哨兵收到了其他哨兵的投票请求,此时对方 epoch 与自己相等,永远都只会投给自己。

因此,同一轮 Epoch 的竞选中,不参选的哨兵会一直投给第一个发给它请求的哨兵参选的哨兵会一直投给自己 。这样,保证了同一轮 Epoch 竞选中,每个投票人只能投给一个人,保证了投票的正确性和公平性

选举过程

总结哨兵的具体选举过程为:

  1. 哨兵确认主节点 odown 后,将自身 current_epoch 加一,将 leader 指向自己,并向其他哨兵发送投票请求。
  2. 其他哨兵接收到投票请求,判断请求中的 epoch 是否大于自己的 current_epoch大于 则更新 current_epoch 并将 leader 指向发送方,然后投票给发送方。 小于或等于 则将票投给自己 leader 字段指向的哨兵(可能是它自己)。
  3. 哨兵每收到一个回复就会将对方的投票结果存储起来,并累计自己的得票数(投给自己的选票数加一,算上自己),当自己得票数超一半且不小于 quorum 时,成为 Leader 并向所有哨兵公示投票结果。
  4. 如果到投票计时截止,哨兵自身的累计票数还没达标,哨兵就会宣告竞选失败,并进入一段随机的等待时间,等待结束之后会再次进行选举
  5. 落选可能是有其他人当选,也可能没人能达标,当哨兵不关心有没有人胜选,因为如果有晋级者,它会主动宣告成功的。
  6. 在等待期间如果没有任何哨兵宣布胜选,则等待时间结束后,哨兵会重新进行选举,此时回到步骤 1。

Master 选取

当选 Leader 后哨兵会进入 SELECT_SLAVE 状态,选取新的主节点。

选取新的主节点遵守以下规则:

  • 排除

    • 已下线的从节点(sdownodown)。
    • 连接断开的节点(PING 超时,disconnected 状态)。
    • 配置了不当 Master 的节点(replica-priority = 0)。
    • 与宕机主节点断开时间过长的从节点(超 10 倍 down-after-milliseconds)。
  • 优先级,从高到低排序:

    • 优先值最高的节点(replica-priority 最小)。
    • 复制偏移量最大的节点。
    • 配置了 runId 的节点。
    • 随机 runId 字典序最小的节点。

如果选取失败,会隔一段时间进行重试,直到选取出新的主节点为止。

Slave 身份去除

当确定新的主节点后,哨兵会进入 SEND_SLAVEOF_NOONE 状态,撤销该节点的 Slave 状态。

复制代码
1:X 19 Aug 2021 08:30:07.587 * +failover-state-send-slaveof-noone slave 172.25.0.102:6379 172.25.0.102 6379 @ mymaster 172.25.0.101 6379

哨兵会发送 slaveof NO ONE 指令给从节点,从节点接收到后会断开它与原主节点的网络连接,重置其复制 ID 并执行持久化重写,并开始将自己的复制身份转为 Master。

提升 Master

在发送指令之后,哨兵会进入 WAIT_PROMOTION 状态,等待该节点将自己提升为主节点。

复制代码
1:X 19 Aug 2021 08:30:07.679 * +failover-state-wait-promotion slave 172.25.0.102:6379 172.25.0.102 6379 @ mymaster 172.25.0.101 6379

等待过程中哨兵会每隔一秒发送一次 INFO 命令给它,直到它的角色变成 Master。

配置从节点

当节点提升为 Master 之后,哨兵会进入 RECONF_SLAVES 状态,更新所有从节点的配置,让他们去复制新的 Master。

复制代码
1:X 19 Mar 2024 13:30:08.374 # +promoted-slave slave 172.25.0.102:6379 172.25.0.102 6379 @ mymaster 172.25.0.101 6379
1:X 19 Mar 2024 13:30:08.374 # +failover-state-reconf-slaves master mymaster 172.25.0.101 6379

哨兵通过向从节点发送 slaveof <ip> <port> 命令即可修改从节点复制配置,并让从节点去复制新的主节点。

相关推荐
TT哇1 小时前
【Java EE初阶】计算机是如何⼯作的
java·redis·java-ee
工一木子4 小时前
URL时间戳参数深度解析:缓存破坏与前端优化的前世今生
前端·缓存
陌殇殇4 小时前
SpringBoot整合SpringCache缓存
spring boot·redis·缓存
晋阳十二夜5 小时前
【压力测试之_Jmeter链接Oracle数据库链接】
数据库·oracle·压力测试
GDAL7 小时前
Node.js v22.5+ 官方 SQLite 模块全解析:从入门到实战
数据库·sqlite·node.js
DCTANT8 小时前
【原创】国产化适配-全量迁移MySQL数据到OpenGauss数据库
java·数据库·spring boot·mysql·opengauss
AI、少年郎10 小时前
Oracle 进阶语法实战:从多维分析到数据清洗的深度应用(第四课)
数据库·oracle
赤橙红的黄10 小时前
自定义线程池-实现任务0丢失的处理策略
数据库·spring
DataGear11 小时前
如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板
javascript·数据库·sql·信息可视化·数据分析·echarts·数据可视化
weixin_4383354011 小时前
分布式锁实现方式:基于Redis的分布式锁实现(Spring Boot + Redis)
数据库·redis·分布式