Kafka 负载均衡挑战及解决思路

本文转载自 Agoda Engineering,介绍了在实际应用中,如何应对 Kafka 负载均衡所遇到的各种挑战,并提出相应的解决思路。本文简要阐述了 Kafka 的并行性机制、常用的分区策略以及在实际操作中遇到的异构硬件、不均匀工作负载等问题。通过深入分析这些挑战,并提供具体的解决方案,本文旨在帮助读者更好地理解和应用 Kafka 的负载均衡技术,从而提高系统的整体性能和稳定性。

以下大部分内容翻译自原文 how-we-solve-load-balancing-challenges-in-apache-kafka,并已获得原作者同意。

思维导图

Kafka 负载均衡解决方案

Kafka 并行性

Kafka 通过分区来实现并行性,如下图所示,生产者(Producer)产生的消息会按照一定的分区策略分配到多个分区(Partition)中,消费组中的每个消费者会分别负责消费其中的若干个分区。

Kafka 分区演示

分区策略:

  • 轮询(Round Robin):默认情况下,Kafka 使用轮询策略将消息均匀地分配到所有分区。
  • 哈希(Key Hashing):如果消息有分区键,Kafka 会对键进行哈希计算,将消息分配到特定的分区。
  • 自定义分区策略:开发者可以实现自定义的分区器(Partitioner)逻辑,以满足特定需求。

如果要使用轮询或者哈希策略来达到“负载均衡”的目的,那么需要满足以下 2 个假设:

  1. 消费者拥有相同的处理能力,
  2. 消息的工作量相等。

然而,在实践中,这些假设往往不成立。

现实挑战

1. 异构硬件

不同代的服务器硬件性能不同,导致处理速率存在差异。例如,使用不同代硬件进行处理的基准显示性能存在显着差异:

不同服务器处理速率差异举例

2. 每条 Kafka 消息的工作负载不均匀

下图显示了在一个时间窗口内到达的 12 条消息。在这里,生产者向该主题中的六个分区中的每一个发布两条消息。因此,每个 worker 消耗来自 2 个分区的数据,这意味着每个 worker 需要处理 4 条消息。

使用循环分区器和循环分配器来分发消息的先前供应系统的演示。每个 worker 都分配有相同数量的消息。

不同的消息可能需要不同的处理步骤集。例如,处理消息可能涉及调用第三方 HTTP 端点,并且不同的响应大小或延迟可能会影响处理速率。此外,对于涉及数据库操作的应用程序,其数据库查询的延迟可能会根据查询参数而波动,从而导致处理速率发生变化。

3. 过度配置问题

由于工作负载和处理效率不同,为了达到系统吞吐量的需求,可能会出现过度配置问题,从而导致资源浪费。

假设我们的高吞吐量和低吞吐量的处理速率分别为 20 msg/s 和 10 msg/s(根据表 1 中的数据进行简化)。使用两个较快的处理器和一个较慢的处理器,我们预计总容量为 20+20+10 = 50 条消息/秒。但是,当保持消息的循环分配时,我们无法达到此容量。下图显示了如果流量持续达到每秒 50 条消息时会发生什么情况。

如果传入流量保持在 50 条消息/秒,则慢速处理器无法处理总体消息 1/3 的负载,从而导致累积延迟。为了避免高延迟,向该系统添加了额外的资源以维持处理。

从这个例子中我们可以看到,我们的处理器服务一次最多只能接受 30 条消息,以防止滞后并确保及时传递更新。

在这种情况下,要实际每秒处理 50 条消息,我们必须总共扩展到 5 台机器,以保证及时处理所有消息。由于这种不适当的分配逻辑(66.7%的过度配置),我们会向该系统过度配置额外的两台机器。

为了每秒处理 50 条消息,我们需要扩展到五台机器以确保及时处理所有消息。由于这种不适当的分配逻辑(66.7% 的过度配置),这会导致向该系统过度配置两台额外的机器。

静态解决方案

1. 在相同的 Pod(机器)上部署

考虑控制服务部署中使用的硬件类型以缓解问题。如果您在虚拟机上部署服务并拥有充足的资源和性能相同的硬件,则此方法是可行的。

然而,由于成本效益和灵活性下降,在私有云环境中通常不建议采用这种策略,主要是因为同时升级所有现有硬件可能具有挑战性。如果它非常适合您的情况,则可以使用Kubernetes 关联性将 Pod 分配给某些类型的节点。

2. 加权负载均衡

如果容量是可预测的并且大部分时间保持静态,则为不同的消费者分配不同的权重可以帮助最大限度地利用可用资源。例如,在为表现较好的消费者赋予更高的权重后,我们可以将更多流量路由给这些消费者。

动态解决方案

虽然我们可以估计消息的容量和工作负载来设计静态规则来确定加权负载平衡策略,但由于以下几个因素,这种方法在实际生产环境中可能并不总是可行:

  • 消息的工作负载并不统一,这使得估计机器容量变得困难。
  • 依赖关系(例如网络和第三方连接)不稳定,有时会导致实际处理中的容量发生变化。
  • 该系统经常添加新功能,增加额外的维护工作以保持权重更新。

为了解决这些问题,我们可以动态监控每个分区中的当前滞后并根据当前流量状况做出相应响应。

有 2 种思路:

  1. 生产者角度:使用自定义算法根据滞后的消息数量来确定每个分区的流量,这种生产者称为滞后感知生产者(Lag-aware Producer)。
  2. 消费者角度:这些消费者旨在监控当前滞后的消息数量,并可以在必要时取消订阅以触发负载重新平衡。通常,可以采用自定义的重新平衡策略来调整分区分配。这种消费者称为滞后感知消费者(Lag-aware Comsumer)。

1. 从生产者角度出发

如此图所示,生产者可以使用自定义算法根据滞后确定每个分区的流量。为了减少对 Kafka 代理的调用次数,系统可以维护一个内部延迟缓存,而不是在发布每条消息之前调用 Kafka 代理。

在此示例中,分区 4 和 6 的延迟比其他分区高得多。应减少从内部生产者发送到这些分区的流量。

使用滞后数据,定制的算法被设计为向经历高滞后的分区发布更少的流量,向低滞后的分区发布更多流量,以平衡每个分区上的工作负载。当滞后平衡且稳定时,此方法应确保消息的均匀分布。

不适用情况:

  1. 纯消费者应用程序:您的应用程序不控制消息生成。
  2. **多个消费者组:**当生成的消息被多个消费者组消费时,生产者可能会为其他消费者组产生不必要的倾斜负载,因为滞后只是特定于一个消费者组的信息。

相同队列长度算法

该算法将每个分区滞后视为处理的队列大小。获取滞后信息后,它会发布适当数量的消息以填充短队列。此方法更适合由于异构硬件而导致的倾斜滞后分布,其中高性能 Pod(机器)在大多数情况下能够更快地处理。

相同队列长度算法的演示。最初,不同队列的长度不同。该算法尝试生成不同数量的消息,以在所有队列中实现相同的队列长度。这里,队列长度和 Kafka lag 是同一个概念,代表尚未处理的消息数量

异常值检测算法

该算法利用统计方法来确定所有分区的上离群值,并暂时停止那些慢速离群值的发布过程。在原文章中,针对 Agoda 的特定需求,他们提出了 IQR(四分位距)和 STD(标准差)异常值检测算法。算法流程图如下所示。

异常值检查算法流程

  • 慢速分区:(已关闭)由于存在延迟,这些分区的消息生成已停止。
  • 好的分区:(打开)照常发布并均匀分发到所有好的分区。
  • OK 分区:(观察/半开放)为了提高性能不佳的机器的性能,当系统尝试将慢速分区提升为良好分区时,会添加一个观察期。通过仅生成一小部分消息并进行观察,可以将该观察阶段优化为“半开放”状态。当滞后获取间隔相对较长时,半开放是有益的,因为它可以防止消费者延迟等待传入消息而更新的滞后数据尚未查询的情况。

2. 从消费者角度出发

这里 Adoga 提出的思路是:遇到高延迟的实例可以主动取消订阅主题以触发重新平衡。在重新平衡期间,可以使用自定义的分配器来平衡所有消费者实例之间的分区。

触发重新平衡的成本非常昂贵,因为急切的重新平衡会停止消费者组中的所有处理。Kafka 2.4中引入的增量协作再平衡协议已经最大限度地减少了性能影响,允许更频繁的再平衡以更好地分配每个分区上的负载。

为了增强重新分配的灵活性,分区的数量应该大于 worker 的数量。这一比率应根据应用程序而有所不同,并假设一个工作线程至少可以处理来自一个分区的负载以避免饥饿。

在此示例中,工作程序 3 在速度较慢的硬件上运行,导致分区 5 和 6 出现更高的延迟。因此,工作程序 3 可能会主动取消订阅主题以触发重新平衡并更有效地重新分配分区。在此示例中,应实现自定义分配器以根据机器指标和滞后信息重新分配分区。

总结

本文从 Kafka 并行性的一般实现出发,探讨了 Kafka 实现负载均衡在现实实践中可能遇到的各种挑战,并从静态调整和动态调整两个方面给出了解决思路,特别注重讨论了动态调整策略,并分别从生产者和消费者的角度提出了解决方案。

总之,通过在 Kafka 中实现负载均衡,可以有效地将工作负载分配到可用资源之间,从而显著提高服务性能。具体的算法和策略需要根据实际情况进行选择和调整。

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

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

相关文章

重生之 SpringBoot3 入门保姆级学习(19、场景整合 CentOS7 Docker 的安装)

重生之 SpringBoot3 入门保姆级学习(19、场景整合 CentOS7 Docker 的安装) 6、场景整合6.1 Docker 6、场景整合 6.1 Docker 官网 https://docs.docker.com/查看自己的 CentOS配置 cat /etc/os-releaseStep 1: 安装必要的一些系统工具 sudo yum insta…

继承-进阶-易错点

子类同名方法隐藏父类方法 即使调用不匹配也不会再去父类寻找&#xff0c;而是直接报错 //下面代码输出结果&#xff1a;( )&#xfeff;class A { public:void f(){ cout<<"A::f()"<<endl; }int a; };class B : public A { public:void f(int a){c…

Excel使用技巧(一)

一. 快速调整数据位置 已经录入数据的表格&#xff0c;要调整某一列的位置怎么办&#xff1f; 只要选中要调整的数据区域&#xff0c;然后按住Shift键不放&#xff0c;光标放到绿色边框位置后&#xff0c;按下鼠标左键不放拖动即可&#xff1a; 二. 取消合并单元格并恢复数据…

Django DeleteView视图

Django 的 DeleteView 是一个基于类的视图&#xff0c;用于处理对象的删除操作。 1&#xff0c;添加视图函数 Test/app3/views.py from django.shortcuts import render# Create your views here. from .models import Bookfrom django.views.generic import ListView class B…

2024050901-重学 Java 设计模式《实战访问者模式》

重学 Java 设计模式&#xff1a;实战访问者模式「模拟家长与校长&#xff0c;对学生和老师的不同视角信息的访问场景」 一、前言 能力&#xff0c;是你前行的最大保障 年龄会不断的增长&#xff0c;但是什么才能让你不慌张。一定是能力&#xff0c;即使是在一个看似还很安稳…

Web后端开发的学习

REST风格 GET:查询用户POST:新增用户POT:修改用户DELETE:删除用户 前后端交互统一的响应结果 记录日志 SLf4j 注解&#xff1a; PathVariable&#xff1a;获取路径的参数ResponseBody :方法的返回值直接作为 HTTP 响应的正文返回,将响应的实体类转为json发送给前端Request…

【RabbitMQ】RabbitMQ 的 6 种工作模式

RabbitMQ 的 6 种工作模式 1.简单模式2.工作队列模式3.交换机模式4.Routing 转发模式5.主题转发模式6.RPC 模式6.1 消息属性6.2 关联标识6.3 工作流程 7.小结 1.简单模式 生产者把消息放入队列&#xff0c;消费者获得消息&#xff0c;如下图所示。这个模式只有 一个消费者、一…

v8中使用TensorBoard进行训练可视化(可用于论文)(补充版,接上一篇文章)

我们可以边训练&#xff0c;边通过TensorBoard观察损失函数的变化&#xff0c;同时也可以通过TensorBoard去查看整体网络yaml结构&#xff0c;不再需要人工根据yaml去画网络结构了。 训练v8的时候&#xff0c;重新打开新的终端&#xff1a; 虚拟环境下输入并执行&#xff1a;&…

redis序列化

文章目录 1、为什么要进行序列化操作&#xff1f;2、序列化方式2.1、自定义序列化2. 2、StringRedisTemplate&#xff08;重点&#xff09; 1、为什么要进行序列化操作&#xff1f; 不进行序列化向redis存入数据代码&#xff1a; SpringBootTest class RedisDemoApplicationT…

日常销售数据分析为什么重要?三个维度全面分析日常销售数据

在当今电子商务的浪潮席卷全球的时代&#xff0c;网店如雨后春笋般涌现&#xff0c;并且竞争日趋激烈。在这样一个充满挑战与机遇的环境中&#xff0c;如何洞察市场动向&#xff0c;把握消费者需求&#xff0c;实现销售业绩的稳步增长&#xff0c;成为每一位电商运营者必须面对…

【YOLOv8改进[注意力]】在YOLOv8中添加GAM注意力 + 含全部代码和详细修改方式 + 手撕结构图

本文将进行在YOLOv8中添加GAM注意力的实践,助力YOLOv8目标检测效果的实践,文中含全部代码、详细修改方式以及手撕结构图。助您轻松理解改进的方法,实现有效涨点。 改进前和改进后的参数对比: 目录 一 GAM 二 在YOLOv8中添加GAM注意力 1 整体修改 2 配置文件

M41T11M6F串行实时时钟-国产兼容RS4C411

RS4C411是一款低功耗串行实时时钟&#xff08;RTC&#xff09;&#xff0c;具有56字节的NVRAM。内置32.768 kHz振荡器&#xff08;外部晶体控制&#xff09;和RAM的前8字节用于时钟/日历功能&#xff0c;并以二进制编码十进制&#xff08;BCD&#xff09;格式配置。地址和数据通…

MacOS下如何使用Tomcat

提示&#xff1a;宝子们&#xff0c;希望文章对你们有所帮助&#xff0c; 请一键三连支持博主下吧&#xff5e; 文章目录 前言一、Tomcat 压缩版二、Tomcat可执行文件版本最后 前言 电脑环境&#xff1a; MacOS Monterey 版本 12.6.8 Apple M1 Tomcat 9.0.83 Java 1.8.0_171 …

滚珠丝杆与梯形丝杆的工作原理与性能差异!

滚珠丝杆和梯形丝杆&#xff08;也称滑动丝杆&#xff09;都是机械设备中常见的两种精密传动元件&#xff0c;两者都是将旋转运动变成直线运动的方式。那么&#xff0c;这两者有什么区别呢&#xff1f;在什么时候选择使用滚珠丝杆&#xff1f;什么时候选用滑动丝杆呢&#xff1…

Petalinux由于网络原因产生的编译错误(3)-qemu-xilinx-system-native 失败

1 获取qemu-xilinx-system-native 失败 编译时遇到qemu-xilinx-system-native 包获取失败&#xff0c;如下图所示&#xff1a; 解决这种错误方法如下&#xff1a; 进入Petalinux 工程&#xff0c;编辑工程下的 project-spec/meta-user/conf/petalinuxbsp.conf 文件&#xff0…

CorelDRAW2024专业版永久免费激活码序列号分享大全

亲爱的设计师们&#xff0c;你们是否有过这样的困扰&#xff1a;想要设计出独具特色的图形作品&#xff0c;但又受限于软件的功能和操作复杂性&#xff1f;今天&#xff0c;我要为大家种草一款神器——CorelDRAW 2024&#xff01;&#x1f389;✨ 作为一个长期使用这款软件的图…

并发、多线程、HTTP连接数有何关系?

在计算机领域&#xff0c;"并发"、"多线程"和"HTTP连接数"是三个重要的概念&#xff0c;它们之间存在着密切的关系。本文将探讨这三者之间的联系以及它们在现代计算机系统中的作用。 一、并发的概念 并发是指系统能够同时处理多个任务或事件的能…

英语学习笔记35——Our village

Our village 我们的村庄 词汇 Vocabulary photograph n. 照片 通常说&#xff1a;photo 复数&#xff1a;photos     picture 复数&#xff1a;pictures 搭配&#xff1a;take a photo 照相 以o结尾的单词复数es的&#xff1a; potato —— potatoes tomato —— tomatoe…

TCP三次握手和四次挥手过程简介(抓包分析,简单易懂,小白)

接上篇 传输层部分 链路层、网络层、传输层和应用层协议详解分析-CSDN博客文章浏览阅读689次&#xff0c;点赞10次&#xff0c;收藏15次。wireshark抓包分析-CSDN博客wireshark是网络包分析工具网络包分析工具的主要作用是尝试捕获网络包&#xff0c;并尝试显示包的尽可能详细…

Selective Kernel Networks(CVPR-2019)

摘要 提出了一种动态选择机制&#xff0c;允许每个神经元根据输入信息的多个尺度自适应调整感受野大小。设计了一种称为选择核&#xff08;SK&#xff09;单元的结构块&#xff0c;利用softmax attention 对不同核大小的多个分支进行融合。对这些分支的不同attention产生融合层…