Talos 网卡负载优化:基于个性化一致性哈希的负载均衡

阅读数:1 2019 年 12 月 23 日 11:16

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

在《万亿级消息背后: 小米消息队列的实践》文章中介绍了小米自研消息队列 Talos 的业务背景和关键问题。

其中在网卡资源优化方面,Talos 主要做了两方面工作:客户端寻址与基于流量的个性化一致性哈希。前者是通过客户端自寻址避免 Server 转发节省网卡资源,后者是通过优化一致性哈希的虚拟节点数配置,调整节点的流量分配情况。

本文将详细介绍后者——基于个性化一致性哈希的流量均衡方法。

业务增长带来的流量均衡需求

Talos 作为高吞吐型的消息队列服务,随着业务增长,带宽往往会成为瓶颈。如果网卡流量不均衡,就会产生集群网卡资源的木桶效应—— 当集群中使用网卡最多的机器达到资源瓶颈就要触发扩容,即便此时该集群其他节点网卡有大量富余,机器成本因此浪费。且随着业务量越来越多,集群规模不断变大,问题变得更加明显。

以小米某线上集群为例,该集群 150 台机器,将各节点的日流量均值绘制成散点图以方便观察其流量均衡程度。其中最高流量 324M,最低 134M,相差两倍不止。

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

分析此问题,机器节点网卡流量的大小,和该节点所 serve 的所有 Partition 流量之和呈正相关。要解决节点间网卡负载不均衡的问题,需要调整 Partition 在各节点的分布情况 (即改变 Partition 的调度关系)。下面我们将简单介绍下优化前 Talos 所使用的调度机制,再来分析如何做到这一点。

基于一致性哈希的调度策略

Talos 使用一致性哈希来约定 Partition 调度关系。简单来讲,一致性哈希可以理解为一个函数,Y = ConsistentHash (X)。任意的 X 取值都能映射为一个固定区间内的唯一数值 Y.

举例说明,我们将 10 节点集群中各节点做映射,用下面的环状图表示。那么区间被分成了 10 份。同样将 Partition 映射也映射到环上,根据其位置区间,来决定由哪个节点所 serve. 集群所有节点都遵从这个约定从而调度信息一致。

实际上,为了使圆环划分的更加均匀和节点上下线更加稳定,每个机器节点将对应多个虚拟节点以力求平均。传统的一致性哈希,每个节点映射的虚拟节点个数是一致的。例如,Talos 每个机器节点对应的虚拟节点个数都是 2000 个。

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

可以理解,使用一致性哈希的调度方式,力求的是 Partition 个数分布的尽量均衡,各 Partition 在调度中的权重是一样的,并不关心 Partition 其他指标 (例如 QPS 和流量) 的差异,且一致性哈希算法的映射关系我们无法干预和调节。

个性化一致性哈希的流量均衡

想要解决这个问题,我们需要引入流量信息参与 Partition 调度决策。通过在调度策略中引入流量反馈机制,调节一致性哈希虚拟节点个数,达到流量均衡。

具体思路是,获得监控数据,对比节点的流量值与集群各节点流量均值。如果该节点流量值较大,则通过减少该节点的虚拟节点个数减少所 serve 的 Partition 个数;如果该节点流量值较小,则通过增多该节点的虚拟节点个数增多所 serve 的 Partition 个数,不断反馈。可以用下图表示。

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

通过监控反馈和虚拟节点不断的调整,该方式最终可以找到符合各节点流量均衡分布的一致性哈希虚拟节点分布,下图简单解释下优化调度效果。

优化前的调度:Partition 个数大致均匀

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

优化后的调度:节点流量均匀

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

相比于引入一个中心节点来实现统一的定制的调度机制,这种方式对 Talos 原有架构来说改动较小,且不会引入复杂的中心节点可用性问题。

流量均衡在 Talos 中的实现

依据上述思想落地到 Talos 业务,需要考虑稳定性问题,分析影响稳定性的因素:

  • 对 Talos 来说,Partition 在节点间的迁移大约在 7s 左右可恢复服务。由于流量均衡过程中会产生 Partition 的迁移,如果短时间内大规模的 Partition 迁移,由于资源的集中调用,不仅会造成恢复时间增长,大规模的迁移还可能带来集群可用性抖动。

  • 类似 HDFS Balance,我们可以设定流量均衡的目标值,例如,设定目标值为 10%,则目标是调整集群最大日均流量与最小日均流量在集群日均流量的 10% 范围内。有些情况下某些目标值我们是无法达到的,这时的调整最终就会变成来回震荡的状况。举个最简单的例子,A 机器 100M 流量,B 机器 50M 流量,单个 Partition 的流量值是 50M,按照 10% 的目标去调整,结果就是会在 A 50M and B 100M 和 A 100M and B 50M 的情况之间来回震荡。不仅达不到目标,还白白带来迁移开销。

  • 还有一些情况,会出现“往坏的方向调节”。依然以一个简单例子说明,A 机器 100M 流量,B 机器 80M 流量,调整目标 10%,单个 Partition 的流量值是 50M,一次调节后变成 A 50M 而 B 130M,均衡度更差。2 和 3 问题的出现,本质上都是由于我们调节的最小粒度是 Partition。

为了避免这些问题,设定了以下机制:

  • 通过监控数据模拟计算,模拟符合预期才触发调整。取得各 Partition 的流量监控数据,带入一致性哈希函数,模拟调整虚拟节点个数并计算各节点流量值;

  • 控制每次迁移的 Partition 个数,保证集群整体稳定性;

  • 计算方差决定是否调整,以防止无谓的震荡调整或往更坏的方向调整。方差能反应离散程度,只有当模拟调整后的方差变小才触发调整;

  • 设定最大调节次数,以设定调整目标无法达到时的无限模拟计算。

最终的实现架构如下:

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

其中 BalanceServer 会负责完成根据阈值和监控值模拟计算,控制迁移量,按规定时间间隔触发等逻辑。集群的可用性不依赖 BalanceServer,BalanceServer 挂掉只是停止了集群的流量均衡调整,集群会继续按照当前的虚拟节点分布进行调度运行,即便出现了集群节点上下线也没关系。

接下来展示下集群均衡的效果,依然以文章开头展示流量图的 Talos 集群为例,将调整后各节点的日流量均值制作成散点图,可以发现优化后各节点流量值明显聚合。经计算,此集群 150 台机器,可节省因网卡达到瓶颈而需要扩容的机器 35 台。

Talos网卡负载优化:基于个性化一致性哈希的负载均衡

值得借鉴的是,通过改变 BalanceServer 引入的监控参数,此方法可以扩展到基于一致性哈希的分布式系统的 QPS 均衡、甚至 CPU 资源和内存资源均衡,只要找到本系统监控指标和均衡指标间的函数关系即可。

相关阅读:

消息队列在企业架构中扮演着什么角色?

万亿级消息背后: 小米消息队列的实践

评论

发布