Pulsar 负载均衡与transaction_coordinator_assign

背景与现状

TC加载到哪个broker上取决于transaction_coordinator_assign-partition-${TC ID}分区加载到哪个broker上。

默认transaction_coordinator_assign有16个分区,因此默认有16个TC,我们需要根据集群机器/broker数目来设置合理的TC个数。
为了保证集群压力均衡,和为了提高服务可用性,我们需要让TC尽量均衡地打散到整个集群机器上,避免所有TC加载到某几台机器。

  • 可用性:比如说,如果16个TC都加载到两三台broker上,那么在集群滚动升级的时候,重启该broker就会导致大量TC同时不可用,这就会明显影响到客户端了。
  • 负载均衡:而且broker承载TC本身也会造成一定的资源消耗,如TC需要跟客户端、TB、TP进行协调,某个broker承载太多TC会导致该机器的负载过高。

transaction_coordinator_assign目前是属于pulsar/system namespace下面的。
目前我们是不对pulsar/system namespace的bundles执行load shedding的,即只会在第一次加载bundle的时候使用hash分配尽量均匀地在当前可用broker列表上均匀地分布,之后不会再对这些bundle进行shedding切换。除非该broker重启导致bundle被卸载,或者管理员执行amdin命令导致bundle被unload,从而触发bundle assign。

存在的问题

那么目前就会有如下问题:
因为broker滚动重启都是有一定时间间隔的,而且一般是一台broker恢复完再重启下一台。
如果集群一开始一台broker都没有在线,然后开始启动集群,那么就会导致所有TC都加载到第一个启动的broker上了
如下图,中间shutdown集群一段时间,然后启动集群,导致16个TC全部加载到broker1上面去了,后面broker2~broker5启动起来后,也不会分配到任何TC。
在这里插入图片描述
这个问题只在集群初启动时会出现,当集群是滚动重启升级时不会有问题,因为集群始终有大量的broker可用,能够保证transaction_coordinator_assign-partition-${TC ID}分区尽量均衡地分配到所有broker上。

要解决这个问题,目前来说也比较简单,集群启动完成后把broker1重启一下,这样所有TC就会重新加载到所有其他broker上了。
如下图:
在这里插入图片描述
还有一个case,举个例子:如果一开始集群broker个数为2,16个TC分配到这两个broker上,后续机器扩容到5台,那么类似地,TC不会分配到新加入的3台机器上。
同样地,对集群滚动重启一轮就没啥问题了。

动态负载均衡

关于是否对transaction_coordinator_assign进行动态负载均衡的分析
前面也说了,目前我们是不对pulsar/system namespace的bundles执行load shedding的。因此transaction_coordinator_assign是不会进行动态负载均衡的
那有必要做动态的负载均衡吗?

动态负载均衡肯定是有好处的,上面问题出现的根源就是无法适应集群加入新broker的情况

bundle负载度量

但是目前所有的负载均衡算法,在分配bundle的时候,都是根据bundle的流量吞吐、消息速率来估测(度量)它会造成多大负载。对于普通业务topic而言这是合适的,但是对于pulsar/system下面的bundle这是不合适的,因为transaction_coordinator_assign本身是没有流量的,transaction_coordinator_assign造成的负载是TC的运行本身
因为shedding算法一般都会从负载大到小挑选bundle执行unload,然后load到低负载broker上,因此在执行shedding时,pulsar/system下面的bundle基本都不会被挑选出来进行shedding,也就是说,开没开动态负载均衡都差不多

因此,就算要启用动态负载均衡,也应该要另起一套负载估测逻辑。那该如何估测呢?

首先,目前客户端在使用事务时,都是直接与所有TC建立链接,然后使用round robin模式挑选TC为它服务,比如说,先在TC 1创建事务txn1,下一次就在TC 2那创建事务txn2。

因此,理论上集群的每个TC造成的负载都是几乎相同的。因此我们可以用TC的个数来作为bundle的负载单位

broker负载度量

还有一个优先级的问题。比如说,broker1加载了所有TC,但是因为没加载什么业务流量,导致CPU负载(资源使用率,或者说scores)比较低,但是broker2、broker3一个TC都没加载,反而因为加载了大部分流量导致CPU负载比较高。
那么我们在分配TC的时候,应不应该把TC切换到broker2、broker3身上?
应该。因为我们可以先保证把TC均摊到三个broker身上,然后再使用原来的动态负载均衡算法把业务流量均衡好就行。

目前的负载均衡算法还使用BrokerData来对Broker本身的负载进行度量,也就是根据CPU负载等资源使用率来判定低载broker
因此我们在对TC进行负载均衡时,也需要更新broker负载的度量标准,新标准也很简单:TC的个数

至此,针对TC的动态负载均衡算法的框架已经搭好了,具体的实现算法就各显神通了。
参考AvgShedder的实现,下面举个例子:
对所有broker承载的TC个数进行统计排序得到一个queue,假设根据承载的TC个数对broker 进行编号,编号为broker1 ~ broker N,broker1承载最多的TC,broker N承载最少的TC。
计算broker1比broker2的TC个数差值M,则如果broker 1上面能找到满足下面条件的bundle:

  • 包含transaction_coordinator_assign-partition-${TC ID}分区的个数小于等于M
    那么就可以将该bundle切换到broker N上面。

猜你喜欢

转载自blog.csdn.net/m0_43406494/article/details/130954079