58消息队列master负载均衡策略设计

Posted 58技术

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了58消息队列master负载均衡策略设计相关的知识,希望对你有一定的参考价值。

背景
WMB是58自主研发的分布式消息队列,具有高可靠、高可用、低延迟、高吞吐等特点。 通过引入一致性算法Paxos,实现了主从数据强一致性、主从秒级自动切换等能力。 为了提升系统的吞吐量,WMB采用多P axos group部署的方式,并以group为单位存储数据,一个Paxos group内对应多个主题,将一段时间主题的数据合并在一起,等待时间或数据积累到阈值后触发一次Paxos propose,批量存储数据。

WMB某主题的发送客户端只会把数据发送到对应group的master节点上,并且消费客户端只会从对应group的master节点上拉取数据。 若master分布不均衡,极端情况下所有group的master都集中到一个节点上,这一个节点会处理整个集群的请求,成为集群的性能瓶颈。 因此WMB提供了master负载均衡策略,当master分布不均衡时,通过平滑夺主机制,在一定周期内实现master的均衡分布,使集群性能达到最优。

58消息队列master负载均衡策略设计


Master选举与续约
在朴素的Paxos算法中是没有master概念的,一般在工程中为了解决Paxos冲突问题,提高Paxos算法性能,会引入master节点的概念。master节点要满足如下强制限制:在任意时刻,Paxos集群有且只有一个master节点或者没有master节点,并且只有master节点可以发起propose。

master的选举过程如下图所示,一般情况下,只有当前无master或节点自身是master时,才可以发起BeMaster操作。 如图示 例中, 当前无 master 节点 A T 1 时刻发起了 BeMaster 操作。 通过 Paxos 算法后,在 T 2 时刻节点 A 成为了集群的 master 角色。 对于节点 A BeMaster 操作 开始计算 master 任期时间,即 T 3 =timeout+ T 1 对于节点 B 从得知 A 节点是 master 后开始计算 master 任期时间,即 认为 master 过期时间 T 2 =timeout+ T1 。因为 T 1 <T 1 ,所以节点 A 认为 master 过期时间 T 3 一定小于节点 B 认为 master 过期时间 T 2 ,在 master 任期内不会出现其他节点尝试抢占 master 的情况

58消息队列master负载均衡策略设计


对于 master 续约,相对简单,只要在 master 的任期内,周期性的由 master 节点再次发起 BeMaster 操作即可完成续约,保证 master 稳定迭代下去。

在WMB中所有节点都会周期性的尝试发起BeMaster操作,只有当前无master节点或自身是master节点时,才会发起成功。 续约过程如下图所示:

58消息队列master负载均衡策略设计
什么是负载均衡
为了最大程度提高WMB集群的性能,master节点的分布应做到负载均衡。在正常情况下,由Paxosmaster选举续约算法保证,master节点可以稳定迭代。而在异常情况下,如网络原因或节点重启等,导致了master的漂移,使得master节点分布发生了均衡的现象。为了使集群再次达到负载均衡的状态,需要对master分布错误的group,进行夺主操作,即理想的master节点对group进行夺主,成为新的master如下图,最开始集群中所有groupmaster都集中在节点S1上,通过夺主后,master均匀分布,集群达到负载均衡的状态。

58消息队列master负载均衡策略设计


谁可以触发负载均衡
谁可以触发负载均衡?在WMB中,为了保证每个节点的负载均衡,会提前计算出所有groupmaster分布,定时找到集群中现有master分布与提前计算出的理想master分布不一致的group。因为在夺主过程中,group是处于可用状态的,为了提高集群的整体可用性,同一时刻只能有一个group处于夺主阶段。WMB中每次只对分布不一致的group中编号最小的group进行夺主。并且当有group已经处于夺主阶段了,则不再发起新的夺主流程。基本流程如下:

58消息队列master负载均衡策略设计


何时可以触发负载均衡
何时可以触发负载均衡? 也就是说执行负载均衡策略之前需要做哪些准备工作? WMB是消息总线服务,所以涉及到两方面的问题: 消费方和发送方。
对于消费方,WMB中消费的进度保存在master中,定时同步给slave节点。 为了保证在夺主后,消费进度一致,即消息不重复、不丢失,在真正开始夺主之前,需要停止消费客户端的消费,并且通知消费客户端上报本地缓存的消费进度到master节点。 待所有客户端消费进度上报结束后,同步消费进度到所有的slave节点上,此操作也是通过Paxos算法保证数据的一致性。

对于发送方,WMB中利用了“提前转发消息的技巧”保证了发送方对夺主过程的无感知。 即因为可以提前得知接下来要成为master角色的节点,在整个夺主的过程中,接收到的所有消息提前转发到即将成为master角色的节点上,让该节点提前承担起master角色的责任,进行propose。 这样,在夺主结束后,该节点成为新的master角色后,继续进行propose,整个过程平滑过度。

如何负载均衡
如何进行负载均衡? 即在前面准备工作结束后,真正的负载均衡方案是如何设计的? 可以看到在负载均衡过程中,消费客户端是停止消费的,发送客户端虽然无感知,但是服务端也进行了一次消息转发,所以负载均衡周期越短越好。 因此整个负载均衡方案的设计就围绕如何尽可能的缩短负载均衡周期而优化演进。
方案一,也是最原始简单的方案。 由当前的master节点发起一次propose,master节点主动放弃续约,即在master任期内不再发起续约操作。 其他非理想节点不再竞争master。 理想节点正常按照续约周期竞争master。 待原master任期过期后,理想节点发起BeMaster操作即可成功,成为新的master节点。 基本示意图如下:

58消息队列master负载均衡策略设计


方案二: 可以看到,前一种方案中理想节点需要被动等待集群中原master过期,并且发起BeMaster是有一定周期的,还需要等待一次续约周期间隔,才可以发起BeMatser操作。 最坏情况下,负载均衡周期为master自然过期时间,续约周期间隔时间与一次Paxos propose时间总和。 负载均衡周期占比最大的就是等待master过期的时间。 为了优化这一部分时间,在WMB中重新定义了master任期的概念。 在原Paxos算法中,master任期的概念为: master节点认为自己的任期为从发起BeMaster操作开始的timeout时间内,slave节点认为master任期为BeMaster操作成功后的timeout时间内。 前文说过,因为这样保证了master认为自己过期的时间一定会提前于salve认为master过期的时间,在master任期内不会有其他节点抢夺master。 但是在设置timeout有效期后,我们无法对其进行额外操作,如果把概念转换一下,把timeout有效期转换为某个时间点,即master任期为某时间点前有效,这样我们就可以通过一个强一致性的算法,把集群中现有master的过期时间点前移,达到提前过期master的效果,减少被动等待master过期的时间。 在WMB中通过master节点发起一次夺主propose,前移master有效时间。 通过Paxos算法保证了前移master有效时间的一致性。 这样新的流程如下:

58消息队列master负载均衡策略设计


方案三: 可以看到,优化后的方案中把负载均衡周期占比最重的等待master过期时间极度的缩小,负载均衡周期为夺主propose时间、等待续约周期时间与BeMaster propose时间总和。 为了做到精益求精,WMB继续对其进行了优化。 既然可以前移master有效时间,可以直接把master过期时间前移到当前时间之前,使得master快速过期。 这样就可以省略等待续约周期的时间,并且合并夺主propose与发起BeMaster propose为一次propose,在这一次propose中,直接过期当前的master,并且理想节点立即进行BeMaster操作。 新的流程如下:

58消息队列master负载均衡策略设计


可以看到,负载均衡周期简化到了两次propose的时间。 这种方案就是最终WMB实际使用的夺主方案。
整体方案
以上从每个部分单独说明了WMB负载均衡策略,接下来从整体上说明一下方案设计。

每个服务节点启动时都会从注册中心拉取该集群负载均衡状态下的group master分布,并启动夺主任务,定时计算master分布错误的group。
如果存在master分布错误,并且当前没有group处于夺主过程中时,则对错误的group中编号最小的group启动夺主流程。 首先判断当前节点是否为理想节点,如果是理想节点,则发送夺主通知到当前的master节点上,并设置自身已经处于夺主阶段。
然后,当前的master节点接收到夺主通知后,设置该group当前的master为“消费不可用”状态,并发送“同步消费offset”命令到该group所关联的所有消费客户端。 等待客户端上传消费offset,为了防止有客户端死链接或网络抖动等原因,该等待操作会有设置过期时间。 在所有客户端都上传消费offset或耗时时间到达阈值后,触发一次同步消费offset到slave节点的propose操作。

以上针对消费方的准备工作结束,保证了在正常情况下,master切换后消息不重复、不丢失,在异常情况下,如: 网络原因导致客户端上传消费offset超时等,会有消息重复消费现象,此时需要业务使用方自行去重。
接下来,再次校验是否有group处于夺主阶段或master在此期间是否有漂移,若没有,则停止该节点的所有propose操作,并设置group处于夺主阶段。 此时该节点接收到的消息都转发到理想节点上,由理想节点进行propose。

以上针对发送方的准备工作结束,开启真正的夺主阶段。 由当前master节点发起夺主propose,在propose成功后,状态机中执行如下操作:

• 前移master过期时间,使得master提前过期

• 若节点为理想节点,则发起BeMaster操作。若节点为非理想节点,则暂停周期性的BeMaster操作,防止非理想节点错误夺主。

在整个周期内,会有校验服务,保证在master发生变化后,或在夺主周期内master连续续约成功两次后,立刻停止这次负载均衡周期,恢复集群状态,等待下一次负载均衡周期。

性能对比
如下图为master负载均衡情况下与master全部集中在一个节点上时的集群最大QPS对比。可以看到,在不同大小的消息字节情况下,负载均衡的集群QPS都远远领先。

总结
在本文中,介绍WMB中为了负载均衡而设计的夺主方案。 通过几代夺主方案的演进优化,对Paxos算法进行了工程上的优化,使其符合WMB的特殊需求。

行文至此,如果有疑问和不足地方,欢迎随时与作者交流与沟通。

作者简介
刘研,框架组件部后端工程师。 参与分布式消息队列WMB架构优化,包括负载均衡机制与任意延迟消息实现等建设。




以上是关于58消息队列master负载均衡策略设计的主要内容,如果未能解决你的问题,请参考以下文章

rocketmq总结以及自动化部署策略

设计精良的网上商城系统,包括前端、后端、数据库、负载均衡、数据库缓存、分库分表、读写分离、全文检索、消息队列等,使用SpringCloud公司框架,基于Java语言开发。该项目可部署到服务器上,不断完

浅谈--技术架构的演进(微服务,负载均衡,异步,消息队列,数据存储,高并发处理,缓存机制)

Rocketmq负载均衡和扩展

深入剖析 RocketMQ 源码 - 负载均衡机制

深入剖析 RocketMQ 源码 - 负载均衡机制