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.mfbz.cn/a/706701.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Arthas查看方法的参数信息情况

使用Arthas查看方法的参数信息情况 前言 最近在排查一个bug,需要看看一个接口方法的传参,但是方法里并没有打印传参,而且还是生产环境,更新包也麻烦,所以,准备安装一下Arthas,通过Arthas可以做…

windows 11中如何设置默认为英文输入法

由于工作需要,我一直在windows7下使用VB6,以前尝试着使用新的系统,但都无法正常安装vb,最近几天由于系统一次作死操作,逼着我安装了win11,并且在其上正常安装了vb6,本想着十分高兴,终…

Ascend C 2.0新特性详解,支撑大模型融合算子高效开发

近日,昇腾算子编程语言Ascend C发布2.0版本,新增支持通算融合MC特性,使能大模型场景下通信和计算并行,提高整网运行性能;提供更丰富的API覆盖当前主流的融合算子开发场景,提升开发效率;同时通过…

大语言模型 (LLM) 红队测试:提前解决模型漏洞

大型语言模型 (LLM) 的兴起具有变革性,以其在自然语言处理和生成方面具有与人类相似的卓越能力,展现出巨大的潜力。然而,LLM 也被发现存在偏见、提供错误信息或幻觉、生成有害内容,甚至进行欺骗行为的情况。一些备受关注的事件包括…

clipboard.js(web页面实现点击复制)

文章目录 codeshow 一个很简单的需求&#xff0c;一个单页面需要一个点击复制的功能 后来在线上找到一个clipboard.js可以实现&#xff0c;这里只用到了最基础的用法&#xff0c;页面样式布局基于bootstrap5.2.3 code <div class"d-flex align-items-center justify-co…

字符设备驱动

目录 demo.c test.c led.h makefile 实验效果 demo.c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include "myled.h" //内核buf char kbuf[…

UITableView之cell复用

关于cell复用的必要性 cellForRowAtIndexPath会随着屏幕滚动而调用&#xff0c;每次出现新行时因为行号变化&#xff0c;就会被调用。 底层原理&#xff1a;当前单元格滚出屏幕时cell销毁&#xff0c;当前单元格又滚回来时cell创建。短时间内频繁创建和销毁cell会影响系统性能…

MySQL 触发器(实验报告)

一、实验名称&#xff1a; 触发器 二、实验日期&#xff1a; 2024 年 6月 8日 三、实验目的&#xff1a; 掌握MySQL触发器的创建及调用&#xff1b; 四、实验用的仪器和材料&#xff1a; 硬件&#xff1a;PC电脑一台&#xff1b; 配置&#xff1a;内存&#xff0c;…

React Native将 ipad 端软件设置为横屏显示后关闭 Modal 弹窗报错

问题&#xff1a; 将 ipad 端软件设置为横屏显示后&#xff0c;关闭 Modal 弹窗报错。 Modal was presented with 0x2 orientations mask but the application only supports 0x18.Add more interface orientations to your apps Info.plist to fix this.NOTE: This will cras…

幸狐RV1106开发板烧录Ubuntu系统与配置SDK,RV1106 LuckFox Pico Max——最新的操作

资料&#xff1a;上手教程 | LUCKFOX WIKI 以及SDK内的文档资料 开发板型号&#xff1a;RV1106 LuckFox Pico Max 烧录系统&#xff1a; Ubuntu 虚拟机系统&#xff1a;Ubuntu 20.04&&Ubuntu22.04 PC系统&#xff1a;win11 占用空间&#xff1a;大概15G 本文主要记…

基于jeecgboot-vue3的Flowable流程-流程处理(一)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 这部分修正一些流程处理中VForm3线上的一些bug问题 1、初始化流程提交与现实的前端页面代码 <!--初始化流程加载默认VForm3表单信息--><el-col :span"16" :offset&qu…

在 Selenium 中更改 User-Agent | 步骤与最佳实践

在 Selenium 中更改 User Agent 是许多网页抓取任务中的关键步骤。它有助于将自动化脚本伪装成常规浏览器&#xff0c;从而避免被网站检测到。本指南将带您了解如何在 Selenium 中更改 Google Chrome 的 User Agent&#xff0c;并提供最佳实践以确保您的网页抓取任务顺利进行。…

IO多路复用简介和代码实例(select函数)

接上篇 阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介-CSDN博客文章浏览阅读95次。阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介https://blog.csdn.net/CSDN_DU666666/article/details/139598410?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%2…

【Linux】易错点——/etc/passwd ; /etc/shadow;ifconfig;route;chmod;ps;mv

/etc/passwd ; /etc/shadow /etc/passwd&#xff1a; 用户账户的详细信息在此文件中更新。 用户名&#xff1a;密码&#xff1a;用户 ID&#xff1a;群组 ID&#xff1a;用户 ID 信息&#xff1a;用户的家目录&#xff1a; Shell /etc/shadow&#xff1a; 用户账户密码在此文…

ssm160基于Java技术的会员制度管理的商品营销系统的设计与实现+vue

商品营销系统计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本商品营销系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理…

【C++取经之路】继承

目录 继承的概念及定义 单继承的格式 继承方式和访问限定符 继承后子类访问基类成员的权限 基类和派生类对象赋值转换 切片 继承中的作用域 引申&#xff1a;重载和隐藏的区别 派生类的默认成员函数 继承与友元 继承与静态成员 如何实现一个不能被继承的类 复杂的…

【SkiaSharp绘图03】SKPaint详解(一)BlendMode混合模式、ColorFilter颜色滤镜

文章目录 SKPaintSKPaint属性BlendMode获取或设置混合模式SKBlendMode 枚举成员效果预览 Color/ColorF获取或设置前景色ColorFilter 颜色滤镜CreateBlendMode 混合模式CreateColorMatrix 颜色转换CreateCompose 组合滤镜CreateHighContrast 高对比度滤镜CreateLighting 照明滤镜…

Java最新面试题(全网最全、最细、附答案)

一、Java基础 1、基础概念与常识Java 语言有哪些特点? 简单易学&#xff08;语法简单&#xff0c;上手容易&#xff09;&#xff1b;面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b;平台无关性&#xff08; Java 虚拟机实现平台无关性&a…

千万级流量冲击下,如何保证极致性能

1 简要介绍 随着互联网的快速发展&#xff0c;网络应用的流量规模不断攀升&#xff0c;特别是在电商大促、明星直播、重大赛事、头条热搜等热点事件中&#xff0c;秒级100w请求成为了常态。在这样的流量冲击下&#xff0c;如何确保系统稳定、高效地处理每一个请求&#xff0c;为…

抖某音号解封释放实名

##抖音账号封禁后如何解封呢 我相信&#xff0c;做过抖音&#xff0c;或者正在做抖音的朋友&#xff0c;都曾面临一种尴尬至极的局面&#xff0c;辛辛苦苦做起来的账号&#xff0c;或者刚刚准备好的账号&#xff0c;在一时之间&#xff0c;竟然被抖音官方封禁了&#xff01; 实…
最新文章