侧边栏壁纸
  • 累计撰写 244 篇文章
  • 累计创建 16 个标签
  • 累计收到 0 条评论
隐藏侧边栏

通过哨兵机制确保 Redis 主从集群的高可用性

kaixindeken
2021-08-12 / 0 评论 / 0 点赞 / 107 阅读 / 2,162 字

引入哨兵机制

线上服务器并不是稳如泰山的,可能会因为各种问题出现故障,比如断电、断网、Redis 进程 Crash 等。如果是从库出现故障,Redis 服务整体依然可用,可如果是主库出现故障,则无法执行 Redis 写入指令,也就意味着 Redis 服务不可用了。

要解决这个问题,应该选择一个从库作为新的主库,然后让其他从库和这个新的主库建立主从同步关系,以便以最快速度恢复 Redis 服务。

如果系统出现这样的问题,总不能每次让运维人员去线上操作吧,因为线上出现故障的时间点不可控,而且手动恢复容易出错,在构建持续交付系统的时候,应该尽量做到无人值守,在这里,我们可以基于 Redis 官方为我们提供的哨兵机制(Sentinel)实现主从的自动切换。

哨兵机制简介

所谓哨兵,其实就是一个独立的 Redis 进程,它会每分每秒孜孜不倦地监控主库从库的运行,就像一个站岗的「哨兵」一样,一旦发现主库/从库挂掉,就会将其标记为下线状态,然后进行后续操作。

这里,我们重点来看下 Redis 哨兵对主库的监控,以及后续的主从切换是如何实现的,总体来看,Redis 哨兵实现主从故障切换需要经历监控、选主(即选择主库)和通知三个阶段。

开始之前,我们可以先看下引入 Redis 哨兵机制后的主从集群架构,以便有一个整体形象的认知:

1.png

可以看到,Redis 哨兵本身也是一个集群架构(类似 Zookeeper/Etcd 集群,通常是3-5个节点,不能少于3个,原因我们后面会解释),以确保其可用性,这样一个哨兵挂了,其他哨兵节点还可以正常运转,从而保证主从切换随时可用。

这样做的另一个用处是在判断主库下线的时候,为了防止误判,需要集群内超过半数以上的哨兵认定主库已下线,才会真正判定主库下线,然后进行主从故障切换。毕竟主从切换一个非常消耗系统资源的操作,只有在主库确实已经下线才应该去进行,否则由于网络抖动导致误判,就是浪费系统资源做一件没有意义的事情了。

主从切换的流程

监控

Redis 哨兵进程在运行时,会周期性地给所有的主/从库发送 PING 命令(心跳连接),用于检测它们是否仍然在线运行,如果主/从库没有在指定时间内响应哨兵发出的 PING 命令,就会被哨兵标记为下线。

这个指定时间可以通过 sentinel 指令配置 down-after-milliseconds 来设置

这里需要注意的是,为了确保主库确实已经下线,而不是误判,Redis 哨兵标记的下线状态又可以进一步细分为「主观下线」和「客观下线」。

对于从库下线直接标记为「主观下线」即可,对于主库下线,为了避免单个节点网络问题导致的误判,Redis 采用了民主协商、少数服从多数的方式进行最终的决策(这也是分布式服务中确保一致性的通用解决方案)。

具体来说,就是在哨兵集群中,判定主库下线不能由一个哨兵说了算,而是需要大多数哨兵认为主库已经「主观下线」,这个时候,主库下线已成客观事实,就会被标记为「客观下线」,然后开始后续的主从切换。

这里的大多数比例是可配置的,通常设置为超过半数,比如对于有 N 个节点的哨兵集群,将这个数字设置为 N/2 + 1 即可,后面演示哨兵集群搭建时会介绍。

选主

当 Redis 主从集群中的主库被标记为「客观下线」,就可以开始主从故障切换了,在此之前,需要按照特定选主规则从所有从库中选择一个从库作为新的主库。

这个选主规则如下:

  • 从在线从库中挑选。被选定的从库必须在线,如果已经被标记为下线状态,肯定是不能作为主库的;
  • 光在线还不够,还要判断从库的网络稳定性。如果现在在线,被选定为主库后就下线了,又要进行新一轮的主从切换,这肯定不合适,那如何判断从库网络的稳定性呢,一般来说,如果从库下线次数超过 10 次,我们就认为该从库网络不稳定,不适合用来做主库。

通过上面两个规则,可以过滤掉那些不能和不适合用来做主库的从库,但是满足这些条件的从库可能不止一个,还需要进一步进行筛选,直到最后剩下一个确定的从库:

  • 如果从库通过 slave-priority 配置了优先级的话,可以将优先级最高的从库作为新的主库,比如不同的 Redis 节点内存、CPU 资源配置可能不同,我们可以为配置好的节点设置更高的优先级;
  • 如果优先级都一样的话,可以将与原来的主库同步程度最高的从库作为新的主库,这里量化的标准是从库中的代表从库同步进度的 slave_repl_offset 值与主库中 master_repl_offset 值的接近程度,越接近则同步程度越高,其实这也从侧面客观反映了这个从库的性能和网络稳定性是所有从库中最好的;
  • 如果上面两个依据仍然不足以筛选出最适合作为新主库的从库,还有最后一个杀手锏:每个 Redis 实例启动后都会分配一个 ID 编号,在从库的优先级和同步程度一样的情况下,Redis 默认会将实例 ID 值最小的从库作为新的主库。

综合以上规则,我们最后肯定可以筛选出新的主库,有了新的主库后,就可以通知其他从库,让它们和新的主库建立主从同步关系,从而构建出新的主从集群。

通知

选出新的主库后,Redis 哨兵会将其 IP 和端口信息发送给其他从库,让它们执行 replicaof 命令,和新主库建立连接,并进行数据同步:

1.png

同时,哨兵还会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。此外,Redis 哨兵还会持续监控原来的主节点,待其恢复后,会将其作为新的主节点的从库:

1.png

0

评论区