[Redis]哨兵

news/2024/9/21 21:37:06/文章来源:https://www.cnblogs.com/DCFV/p/18333205

这次聊聊,Redis 的哨兵机制。

image

为什么要有哨兵机制?

在 Redis 的主从架构中,由于主从模式是读写分离的,如果主节点(master)挂了,那么将没有主节点来服务客户端的写操作请求,也没有主节点给从节点(slave)进行数据同步了。

image

这时如果要恢复服务的话,需要人工介入,选择一个「从节点」切换为「主节点」,然后让其他从节点指向新的主节点,同时还需要通知上游那些连接 Redis 主节点的客户端,将其配置中的主节点 IP 地址更新为「新主节点」的 IP 地址。

这样也不太“智能”了,要是有一个节点能监控「主节点」的状态,当发现主节点挂了,它自动将一个「从节点」切换为「主节点」的话,那么可以节省我们很多事情啊!

Redis 在 2.8 版本以后提供的哨兵(Sentinel)机制,它的作用是实现主从节点故障转移。它会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端。

哨兵机制是如何工作的?

哨兵其实是一个运行在特殊模式下的 Redis 进程,所以它也是一个节点。从“哨兵”这个名字也可以看得出来,它相当于是“观察者节点”,观察的对象是主从节点。

当然,它不仅仅是观察那么简单,在它观察到有异常的状况下,会做出一些“动作”,来修复异常状态。

哨兵节点主要负责三件事情:监控选主通知

image

所以,我们重点要学习这三件事情:

  • 哨兵节点是如何监控节点的?又是如何判断主节点是否真的故障了?
  • 根据什么规则选择一个从节点切换为主节点?
  • 怎么把新主节点的相关信息通知给从节点和客户端呢?

如何判断主节点真的故障了?

哨兵会每隔 1 秒给所有主从节点发送 PING 命令,当主从节点收到 PING 命令后,会发送一个响应命令给哨兵,这样就可以判断它们是否在正常运行。

image

如果主节点或者从节点没有在规定的时间内响应哨兵的 PING 命令,哨兵就会将它们标记为「主观下线」。这个「规定的时间」是配置项 down-after-milliseconds 参数设定的,单位是毫秒

主观下线?难道还有客观下线?

是的没错,客观下线只适用于主节点。

之所以针对「主节点」设计「主观下线」和「客观下线」两个状态,是因为有可能「主节点」其实并没有故障,可能只是因为主节点的系统压力比较大或者网络发送了拥塞,导致主节点没有在规定时间内响应哨兵的 PING 命令。

所以,为了减少误判的情况,哨兵在部署的时候不会只部署一个节点,而是用多个节点部署成哨兵集群(最少需要三台机器来部署哨兵集群),通过多个哨兵节点一起判断,就可以就可以避免单个哨兵因为自身网络状况不好,而误判主节点下线的情况。同时,多个哨兵的网络同时不稳定的概率较小,由它们一起做决策,误判率也能降低。

具体是怎么判定主节点为「客观下线」的呢?

当一个哨兵判断主节点为「主观下线」后,就会向其他哨兵发起命令,其他哨兵收到这个命令后,就会根据自身和主节点的网络状况,做出赞成投票或者拒绝投票的响应。

image

当这个哨兵的赞同票数达到哨兵配置文件中的quorum配置项设定的值后,这时主节点就会被该哨兵标记为「客观下线」

例如,现在有 3 个哨兵,quorum 配置的是 2,那么一个哨兵需要 2 张赞成票,就可以标记主节点为“客观下线”了。这 2 张赞成票包括哨兵自己的一张赞成票和另外两个哨兵的赞成票。

PS:quorum 的值一般设置为哨兵个数的二分之一加 1,例如 3 个哨兵就设置 2。

哨兵判断完主节点客观下线后,哨兵就要开始在多个「从节点」中,选出一个从节点来做新主节点。

由哪个哨兵进行主从故障转移?

前面说过,为了更加“客观”的判断主节点故障了,一般不会只由单个哨兵的检测结果来判断,而是多个哨兵一起判断,这样可以减少误判概率,所以哨兵是以哨兵集群的方式存在的。

问题来了,由哨兵集群中的哪个节点进行主从故障转移呢?

所以这时候,还需要在哨兵集群中选出一个 leader,让 leader 来执行主从切换。

选举 leader 的过程其实是一个投票的过程,在投票开始前,肯定得有个「候选者」。

那谁来作为候选者呢?

哪个哨兵节点判断主节点为「客观下线」,这个哨兵节点就是候选者,所谓的候选者就是想当 Leader 的哨兵。

举个例子,假设有三个哨兵。当哨兵 B 先判断到主节点「主观下线后」,就会给其他实例发送 is-master-down-by-addr 命令。接着,其他哨兵会根据自己和主节点的网络连接情况,做出赞成投票或者拒绝投票的响应。

当哨兵 B 收到赞成票数达到哨兵配置文件中的 quorum 配置项设定的值后,就会将主节点标记为「客观下线」,此时的哨兵 B 就是一个 Leader 候选者。

候选者如何选举成为 Leader?

候选者会向其他哨兵发送命令,表明希望成为 Leader 来执行主从切换,并让所有其他哨兵对它进行投票。

每个哨兵只有一次投票机会,如果用完后就不能参与投票了,可以投给自己或投给别人,但是只有候选者才能把票投给自己。

那么在投票过程中,任何一个「候选者」,要满足两个条件:

  • 第一,拿到半数以上的赞成票;
  • 第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。

举个例子,假设哨兵节点有 3 个,quorum 设置为 2,那么任何一个想成为 Leader 的哨兵只要拿到 2 张赞成票,就可以选举成功了。如果没有满足条件,就需要重新进行选举。

image

这时候有的同学就会问了,如果某个时间点,刚好有两个哨兵节点判断到主节点为客观下线,那这时不就有两个候选者了?这时该如何决定谁是 Leader 呢?

每位候选者都会先给自己投一票,然后向其他哨兵发起投票请求。如果投票者先收到「候选者 A」的投票请求,就会先投票给它,如果投票者用完投票机会后,收到「候选者 B」的投票请求后,就会拒绝投票。这时,候选者 A 先满足了上面的那两个条件,所以「候选者 A」就会被选举为 Leader。

为什么哨兵节点至少要有 3 个?

如果哨兵集群中只有 2 个哨兵节点,此时如果一个哨兵想要成功成为 Leader,必须获得 2 票,而不是 1 票。

所以,如果哨兵集群中有个哨兵挂掉了,那么就只剩一个哨兵了,如果这个哨兵想要成为 Leader,这时票数就没办法达到 2 票,就无法成功成为 Leader,这时是无法进行主从节点切换的。

因此,通常我们至少会配置 3 个哨兵节点。这时,如果哨兵集群中有个哨兵挂掉了,那么还剩下两个哨兵,如果这个哨兵想要成为 Leader,这时还是有机会达到 2 票的,所以还是可以选举成功的,不会导致无法进行主从节点切换。

当然,你要问,如果 3 个哨兵节点,挂了 2 个怎么办?这个时候得人为介入了,或者增加多一点哨兵节点。

再说一个问题,Redis 1 主 4 从,5 个哨兵,quorum 设置为 3,如果 2 个哨兵故障,当主节点宕机时,哨兵能否判断主节点“客观下线”?主从能否自动切换?

哨兵集群可以判定主节点“客观下线”。哨兵集群还剩下 3 个哨兵,当一个哨兵判断主节点“主观下线”后,询问另外 2 个哨兵后,有可能能拿到 3 张赞同票,这时就达到了 quorum 的值,因此,哨兵集群可以判定主节点为“客观下线”。

哨兵集群可以完成主从切换。当有个哨兵标记主节点为「客观下线」后,就会进行选举 Leader 的过程,因为此时哨兵集群还剩下 3 个哨兵,那么还是可以拿到半数以上(5/2+1=3)的票,而且也达到了 quorum 值,满足了选举 Leader 的两个条件,所以就能选举成功,因此哨兵集群可以完成主从切换。

如果 quorum 设置为 2,并且如果有 3 个哨兵故障的话。此时哨兵集群还是可以判定主节点为“客观下线”,但是哨兵不能完成主从切换了,大家可以自己推演下。

如果 quorum 设置为 3,并且如果有 3 个哨兵故障的话,哨兵集群即不能判定主节点为“客观下线”,也不能完成主从切换了。

可以看到,quorum 为 2 的时候,并且如果有 3 个哨兵故障的话,虽然可以判定主节点为“客观下线”,但是不能完成主从切换,这样感觉「判定主节点为客观下线」这件事情白做了一样,既然这样,还不如不要做,quorum 为 3 的时候,就可以避免这种无用功。

所以,quorum 的值建议设置为哨兵个数的二分之一加 1,例如 3 个哨兵就设置 2,5 个哨兵设置为 3,而且哨兵节点的数量应该是奇数。

主从故障转移的过程是怎样的?

在哨兵集群中通过投票的方式,选举出了哨兵 leader 后,就可以进行主从故障转移的过程了,如下图:

image

主从故障转移操作包含以下四个步骤:

  • 第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点。
  • 第二步:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」;
  • 第三步:将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;
  • 第四步:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点;

步骤一:选出新主节点

故障转移操作第一步要做的就是在已下线主节点属下的所有「从节点」中,挑选出一个状态良好、数据完整的从节点,然后向这个「从节点」发送 SLAVEOF no one 命令,将这个「从节点」转换为「主节点」。

那么多「从节点」,到底选择哪个从节点作为新主节点的?

随机的方式好吗?随机的方式,实现起来很简单,但是如果选到一个网络状态不好的从节点作为新主节点,那么可能在将来不久又要做一次主从故障迁移。

所以,我们首先要把网络状态不好的从节点给过滤掉。首先把已经下线的从节点过滤掉,然后把以往网络连接状态不好的从节点也给过滤掉。

怎么判断从节点之前的网络连接状态不好呢?

Redis 有个叫 down-after-milliseconds * 10 配置项,其 down-after-milliseconds 是主从节点断连的最大连接超时时间。如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,我们就可以认为主从节点断连了。如果发生断连的次数超过了 10 次,就说明这个从节点的网络状况不好,不适合作为新主节点。

至此,我们就把网络状态不好的从节点过滤掉了,接下来要对所有从节点进行三轮考察:优先级、复制进度、ID 号。在进行每一轮考察的时候,哪个从节点优先胜出,就选择其作为新主节点。

  • 第一轮考察:哨兵首先会根据从节点的优先级来进行排序,优先级越小排名越靠前,
  • 第二轮考察:如果优先级相同,则查看复制的下标,哪个从「主节点」接收的复制数据多,哪个就靠前。
  • 第三轮考察:如果优先级和下标都相同,就选择从节点 ID 较小的那个。

第一轮考察:优先级最高的从节点胜出

Redis 有个叫 slave-priority 配置项,可以给从节点设置优先级。

每一台从节点的服务器配置不一定是相同的,我们可以根据服务器性能配置来设置从节点的优先级。

比如,如果「A 从节点」的物理内存是所有从节点中最大的,那么我们可以把「A 从节点」的优先级设置成最高。这样当哨兵进行第一轮考虑的时候,优先级最高的 A 从节点就会优先胜出,于是就会成为新主节点。

第二轮考察:复制进度最靠前的从节点胜出

如果在第一轮考察中,发现优先级最高的从节点有两个,那么就会进行第二轮考察,比较两个从节点哪个复制进度。

什么是复制进度?主从架构中,主节点会将写操作同步给从节点,在这个过程中,主节点会用 master_repl_offset 记录当前的最新写操作在 repl_backlog_buffer 中的位置(如下图中的「主服务器已经写入的数据」的位置),而从节点会用 slave_repl_offset 这个值记录当前的复制进度(如下图中的「从服务器要读的位置」的位置)。

image

如果某个从节点的 slave_repl_offset 最接近 master_repl_offset,说明它的复制进度是最靠前的,于是就可以将它选为新主节点。

第三轮考察:ID 号小的从节点胜出

如果在第二轮考察中,发现有两个从节点优先级和复制进度都是一样的,那么就会进行第三轮考察,比较两个从节点的 ID 号,ID 号小的从节点胜出。

什么是 ID 号?每个从节点都有一个编号,这个编号就是 ID 号,是用来唯一标识从节点的。

到这里,选主的事情终于结束了。简单给大家总结下:

image

在选举出从节点后,哨兵 leader 向被选中的从节点发送 SLAVEOF no one 命令,让这个从节点解除从节点的身份,将其变为新主节点。

如下图,哨兵 leader 向被选中的从节点 server2 发送 SLAVEOF no one 命令,将该从节点升级为新主节点。
image

在发送 SLAVEOF no one 命令之后,哨兵 leader 会以每秒一次的频率向被升级的从节点发送 INFO 命令(没进行故障转移之前,INFO 命令的频率是每十秒一次),并观察命令回复中的角色信息,当被升级节点的角色信息从原来的 slave 变为 master 时,哨兵 leader 就知道被选中的从节点已经顺利升级为主节点了。

如下图,选中的从节点 server2 升级成了新主节点:

image

步骤二:将从节点指向新主节点

当新主节点出现之后,哨兵 leader 下一步要做的就是,让已下线主节点属下的所有「从节点」指向「新主节点」,这一动作可以通过向「从节点」发送 SLAVEOF 命令来实现。

如下图,哨兵 leader 向所有从节点(server3 和 server4)发送 SLAVEOF ,让它们成为新主节点的从节点。

image

所有从节点指向新主节点后的拓扑图如下:

image

步骤三:通知客户的主节点已更换

经过前面一系列的操作后,哨兵集群终于完成主从切换的工作,那么新主节点的信息要如何通知给客户端呢?

这主要通过 Redis 的发布者/订阅者机制来实现的。每个哨兵节点提供发布者/订阅者机制,客户端可以从哨兵订阅消息。

哨兵提供的消息订阅频道有很多,不同频道包含了主从节点切换过程中的不同关键事件,几个常见的事件如下:

客户端和哨兵建立连接后,客户端会订阅哨兵提供的频道。主从切换完成后,哨兵就会向 +switch-master 频道发布新主节点的 IP 地址和端口的消息,这个时候客户端就可以收到这条信息,然后用这里面的新主节点的 IP 地址和端口进行通信了。

通过发布者/订阅者机制机制,有了这些事件通知,客户端不仅可以在主从切换后得到新主节点的连接信息,还可以监控到主从节点切换过程中发生的各个重要事件。这样,客户端就可以知道主从切换进行到哪一步了,有助于了解切换进度。

步骤四:将旧主节点变为从节点

故障转移操作最后要做的是,继续监视旧主节点,当旧主节点重新上线时,哨兵集群就会向它发送 SLAVEOF 命令,让它成为新主节点的从节点,如下图:

image

至此,整个主从节点的故障转移的工作结束。

哨兵集群是如何组成的?

前面提到了 Redis 的发布者/订阅者机制,那就不得不提一下哨兵集群的组成方式,因为它也用到了这个技术。

在我第一次搭建哨兵集群的时候,当时觉得很诧异。因为在配置哨兵的信息时,竟然只需要填下面这几个参数,设置主节点名字、主节点的 IP 地址和端口号以及 quorum 值。

sentinel monitor

不需要填其他哨兵节点的信息,我就好奇它们是如何感知对方的,又是如何组成哨兵集群的?

后面才了解到,哨兵节点之间是通过 Redis 的发布者/订阅者机制来相互发现的。

在主从集群中,主节点上有一个名为__sentinel__:hello的频道,不同哨兵就是通过它来相互发现,实现互相通信的。

在下图中,哨兵 A 把自己的 IP 地址和端口的信息发布到__sentinel__:hello 频道上,哨兵 B 和 C 订阅了该频道。那么此时,哨兵 B 和 C 就可以从这个频道直接获取哨兵 A 的 IP 地址和端口号。然后,哨兵 B、C 可以和哨兵 A 建立网络连接。

image

通过这个方式,哨兵 B 和 C 也可以建立网络连接,这样一来,哨兵集群就形成了。

哨兵集群会对「从节点」的运行状态进行监控,那哨兵集群如何知道「从节点」的信息?

主节点知道所有「从节点」的信息,所以哨兵会每 10 秒一次的频率向主节点发送 INFO 命令来获取所有「从节点」的信息。

如下图所示,哨兵 B 给主节点发送 INFO 命令,主节点接受到这个命令后,就会把从节点列表返回给哨兵。接着,哨兵就可以根据从节点列表中的连接信息,和每个从节点建立连接,并在这个连接上持续地对从节点进行监控。哨兵 A 和 C 可以通过相同的方法和从节点建立连接。

image

正是通过 Redis 的发布者/订阅者机制,哨兵之间可以相互感知,然后组成集群,同时,哨兵又通过 INFO 命令,在主节点里获得了所有从节点连接信息,于是就能和从节点建立连接,并进行监控了。

总结

Redis 在 2.8 版本以后提供的哨兵(Sentinel)机制,它的作用是实现主从节点故障转移。它会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端。

哨兵一般是以集群的方式部署,至少需要 3 个哨兵节点,哨兵集群主要负责三件事情:监控、选主、通知。

哨兵节点通过 Redis 的发布者/订阅者机制,哨兵之间可以相互感知,相互连接,然后组成哨兵集群,同时哨兵又通过 INFO 命令,在主节点里获得了所有从节点连接信息,于是就能和从节点建立连接,并进行监控了。

1、第一轮投票:判断主节点下线

当哨兵集群中的某个哨兵判定主节点下线(主观下线)后,就会向其他哨兵发起命令,其他哨兵收到这个命令后,就会根据自身和主节点的网络状况,做出赞成投票或者拒绝投票的响应。

当这个哨兵的赞同票数达到哨兵配置文件中的 quorum 配置项设定的值后,这时主节点就会被该哨兵标记为「客观下线」。

2、第二轮投票:选出哨兵 leader

某个哨兵判定主节点客观下线后,该哨兵就会发起投票,告诉其他哨兵,它想成为 leader,想成为 leader 的哨兵节点,要满足两个条件:

第一,拿到半数以上的赞成票;
第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。
3、由哨兵 leader 进行主从故障转移

选举出了哨兵 leader 后,就可以进行主从故障转移的过程了。该操作包含以下四个步骤:

第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点,选择的规则:
过滤掉已经离线的从节点;
过滤掉历史网络连接状态不好的从节点;
将剩下的从节点,进行三轮考察:优先级、复制进度、ID 号。在每一轮考察过程中,如果找到了一个胜出的从节点,就将其作为新主节点。
第二步:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」;
第三步:将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;
第四步:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/774204.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一屏掌控物流风云:数据大屏开启高效运营时代

在日新月异的数字化浪潮中,物流行业正以前所未有的速度迈向智能化、高效化的新纪元。作为这一变革的核心驱动力之一,山海鲸可视化搭建的物流订单数据监控大屏以其强大的信息整合能力、实时的数据可视化展示以及精准的业务决策支持,成为了现代物流企业不可或缺的智慧中枢。想…

ofd轻阅读超大文件优化方案

本人使用Typescript开发了一款ofd 阅读器,参见文章《ofd轻阅读》。web端实现阅读功能有两种方案: ofd转svg;使用h5 canvas。 两种方案各有优劣,本人采用了canvas方案, 劣势:开发难点较大,需要处理更多的细节(比如:文字选中)。 优势:对细节掌控能力更强,能满足用户更…

笔记:从Aurora 8b/10b 到Aurora 64b/66b (一):Aurora 8b/10b

参考: https://www.xilinx.com/products/intellectual-property/aurora8b10b.html#documentation https://docs.amd.com/r/en-US/pg046-aurora-8b10b https://docs.amd.com/v/u/en-US/aurora_8b10b_ds797 https://mp.weixin.qq.com/s/gT4QUgvoFF6UI0PAhfEPvQ 补丁: Aurora 系…

矩阵指数的定义

人就像是被蒙着眼推磨的驴子,生活就像一条鞭子;当鞭子抽到你背上时,你就只能一直往前走,虽然连你也不知道要走到什么时候为止,便一直这么坚持着。

虚树【学习笔记】

为什么要用虚树? 例题 在某些树上问题中,对于某次询问,我们并不需要用到全部的树上的点: 例如,例题中:总点数 \(n \le 2.5\times10^5\) 询问次数 \(m \le 5\times10^5\) 询问的点数 \(\sum k_i \le 5\times10^5\)我们可以发现其实每次询问均摊下来的询问点数k并不多,但如…

组合机床与自动化加工技术的网站开发

这两天一直在学习如何排版,开发一个网站,我运用了前几天所学的vue基本语法将网站的大致模样copy下来这期间我查找了不少知识 比如照片如何在网页中不变性的缩放,通过研究我运用class固定结构和class="container"属性将组件固定形成此网页

火山引擎VeDI数据技术分享:两个步骤,为Parquet降本提效

本文将介绍字节跳动基于Parquet格式降本增效的技术原理和在具体业务中的实践,首先介绍了Parquet格式在字节跳动的应用,然后将结合具体的应用场景:小文件合并和列级TTL ,从问题产生的背景和解决问题的技术方案出发,介绍如何基于Parquet格式实现降本增效的目标。更多技术交流…

图片预加载和懒加载

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣图片预加载和图片懒加载是网页优化的两种常见技术,它们可以提升用户体验并改善网页性能。 图片预加载(Image Preloading): 图片预加载是指在页面加载时提前加载图片,使其缓存在浏览器中,当用户需要查看这些图片时,…

P4062 Yazid 的新生舞会

谨以此文纪念一场灾难 来给这位善良的人的人点点赞首先 题面中所指的众数为 绝对众数(绝对众数是指在一组数据中出现次数 \(超过\) 总数一半的数值。), 下文的所有众数也指绝对众数。 有以下性质任意一个区间的绝对众数的数值唯一如果\(x\)是区间\([l,r]\)的众数,那么对于\…

KubeSphere 部署向量数据库 Milvus 实战指南

作者:运维有术星主Milvus 是一个为通用人工智能(GenAI)应用而构建的开源向量数据库。它以卓越的性能和灵活性,提供了一个强大的平台,用于存储、搜索和管理大规模的向量数据。Milvus 能够执行高速搜索,并以最小的性能损失扩展到数百亿向量。其分布式架构确保了系统的高可用…

利用DYNAMIXEL智能伺服舵机从《传送门2》中打造一个更优质的动画机器人小麦克利(Wheatley)

原文链接:https://www.youtube.com/watch?v=OEn9hZ-Tw1E这段视频由ROBOTIS提供! 大家好,我想给大家推荐一个精彩视频,在视频中展示了如何制作《传送门2》中的动画机器人小麦克利(Wheatley)。看看是如何利用DYNAMIXEL智能伺服系统让小麦克利活起来的。对于那些可能想设计…

GIS视效升级!零代码添加环境效果,支持多种GIS影像协议

在当今的数字化时代,GIS(地理信息系统)不再仅仅只能通过一些二维示意图或简陋的三维地形图表示,它可以通过专业的软件简单升级视效。想象一下,在你的GIS场景中,阳光明媚的天气、突如其来的暴风雨、缭绕的晨雾,统统都可以通过零代码的操作轻松实现,而这个效果我是使用一…