Kafka 负载均衡挑战及解决思路
本文转载自 Agoda Engineering,介绍了在实际应用中,如何应对 Kafka 负载均衡所遇到的各种挑战,并提出相应的解决思路。本文简要阐述了 Kafka 的并行性机制、常用的分区策略以及在实际操作中遇到的异构硬件、不均匀工作负载等问题。通过深入分析这些挑战,并提供具体的解决方案,本文旨在帮助读者更好地理解和应用 Kafka 的负载均衡技术,从而提高系统的整体性能和稳定性。
以下大部分内容翻译自原文 how-we-solve-load-balancing-challenges-in-apache-kafka,并已获得原作者同意。
思维导图
Kafka 并行性
Kafka 通过分区来实现并行性,如下图所示,生产者(Producer)产生的消息会按照一定的分区策略分配到多个分区(Partition)中,消费组中的每个消费者会分别负责消费其中的若干个分区。
分区策略:
- 轮询(Round Robin):默认情况下,Kafka 使用轮询策略将消息均匀地分配到所有分区。
- 哈希(Key Hashing):如果消息有分区键,Kafka 会对键进行哈希计算,将消息分配到特定的分区。
- 自定义分区策略:开发者可以实现自定义的分区器(Partitioner)逻辑,以满足特定需求。
如果要使用轮询或者哈希策略来达到“负载均衡”的目的,那么需要满足以下 2 个假设:
- 消费者拥有相同的处理能力,
- 消息的工作量相等。
然而,在实践中,这些假设往往不成立。
现实挑战
1. 异构硬件
不同代的服务器硬件性能不同,导致处理速率存在差异。例如,使用不同代硬件进行处理的基准显示性能存在显着差异:
2. 每条 Kafka 消息的工作负载不均匀
下图显示了在一个时间窗口内到达的 12 条消息。在这里,生产者向该主题中的六个分区中的每一个发布两条消息。因此,每个 worker 消耗来自 2 个分区的数据,这意味着每个 worker 需要处理 4 条消息。
不同的消息可能需要不同的处理步骤集。例如,处理消息可能涉及调用第三方 HTTP 端点,并且不同的响应大小或延迟可能会影响处理速率。此外,对于涉及数据库操作的应用程序,其数据库查询的延迟可能会根据查询参数而波动,从而导致处理速率发生变化。
3. 过度配置问题
由于工作负载和处理效率不同,为了达到系统吞吐量的需求,可能会出现过度配置问题,从而导致资源浪费。
假设我们的高吞吐量和低吞吐量的处理速率分别为 20 msg/s 和 10 msg/s(根据表 1 中的数据进行简化)。使用两个较快的处理器和一个较慢的处理器,我们预计总容量为 20+20+10 = 50 条消息/秒。但是,当保持消息的循环分配时,我们无法达到此容量。下图显示了如果流量持续达到每秒 50 条消息时会发生什么情况。
从这个例子中我们可以看到,我们的处理器服务一次最多只能接受 30 条消息,以防止滞后并确保及时传递更新。
在这种情况下,要实际每秒处理 50 条消息,我们必须总共扩展到 5 台机器,以保证及时处理所有消息。由于这种不适当的分配逻辑(66.7%的过度配置),我们会向该系统过度配置额外的两台机器。
为了每秒处理 50 条消息,我们需要扩展到五台机器以确保及时处理所有消息。由于这种不适当的分配逻辑(66.7% 的过度配置),这会导致向该系统过度配置两台额外的机器。
静态解决方案
1. 在相同的 Pod(机器)上部署
考虑控制服务部署中使用的硬件类型以缓解问题。如果您在虚拟机上部署服务并拥有充足的资源和性能相同的硬件,则此方法是可行的。
然而,由于成本效益和灵活性下降,在私有云环境中通常不建议采用这种策略,主要是因为同时升级所有现有硬件可能具有挑战性。如果它非常适合您的情况,则可以使用Kubernetes 关联性将 Pod 分配给某些类型的节点。
2. 加权负载均衡
如果容量是可预测的并且大部分时间保持静态,则为不同的消费者分配不同的权重可以帮助最大限度地利用可用资源。例如,在为表现较好的消费者赋予更高的权重后,我们可以将更多流量路由给这些消费者。
动态解决方案
虽然我们可以估计消息的容量和工作负载来设计静态规则来确定加权负载平衡策略,但由于以下几个因素,这种方法在实际生产环境中可能并不总是可行:
- 消息的工作负载并不统一,这使得估计机器容量变得困难。
- 依赖关系(例如网络和第三方连接)不稳定,有时会导致实际处理中的容量发生变化。
- 该系统经常添加新功能,增加额外的维护工作以保持权重更新。
为了解决这些问题,我们可以动态监控每个分区中的当前滞后并根据当前流量状况做出相应响应。
有 2 种思路:
- 生产者角度:使用自定义算法根据滞后的消息数量来确定每个分区的流量,这种生产者称为滞后感知生产者(Lag-aware Producer)。
- 消费者角度:这些消费者旨在监控当前滞后的消息数量,并可以在必要时取消订阅以触发负载重新平衡。通常,可以采用自定义的重新平衡策略来调整分区分配。这种消费者称为滞后感知消费者(Lag-aware Comsumer)。
1. 从生产者角度出发
如此图所示,生产者可以使用自定义算法根据滞后确定每个分区的流量。为了减少对 Kafka 代理的调用次数,系统可以维护一个内部延迟缓存,而不是在发布每条消息之前调用 Kafka 代理。
使用滞后数据,定制的算法被设计为向经历高滞后的分区发布更少的流量,向低滞后的分区发布更多流量,以平衡每个分区上的工作负载。当滞后平衡且稳定时,此方法应确保消息的均匀分布。
不适用情况:
- 纯消费者应用程序:您的应用程序不控制消息生成。
- **多个消费者组:**当生成的消息被多个消费者组消费时,生产者可能会为其他消费者组产生不必要的倾斜负载,因为滞后只是特定于一个消费者组的信息。
相同队列长度算法
该算法将每个分区滞后视为处理的队列大小。获取滞后信息后,它会发布适当数量的消息以填充短队列。此方法更适合由于异构硬件而导致的倾斜滞后分布,其中高性能 Pod(机器)在大多数情况下能够更快地处理。
异常值检测算法
该算法利用统计方法来确定所有分区的上离群值,并暂时停止那些慢速离群值的发布过程。在原文章中,针对 Agoda 的特定需求,他们提出了 IQR(四分位距)和 STD(标准差)异常值检测算法。算法流程图如下所示。
- 慢速分区:(已关闭)由于存在延迟,这些分区的消息生成已停止。
- 好的分区:(打开)照常发布并均匀分发到所有好的分区。
- OK 分区:(观察/半开放)为了提高性能不佳的机器的性能,当系统尝试将慢速分区提升为良好分区时,会添加一个观察期。通过仅生成一小部分消息并进行观察,可以将该观察阶段优化为“半开放”状态。当滞后获取间隔相对较长时,半开放是有益的,因为它可以防止消费者延迟等待传入消息而更新的滞后数据尚未查询的情况。
2. 从消费者角度出发
这里 Adoga 提出的思路是:遇到高延迟的实例可以主动取消订阅主题以触发重新平衡。在重新平衡期间,可以使用自定义的分配器来平衡所有消费者实例之间的分区。
触发重新平衡的成本非常昂贵,因为急切的重新平衡会停止消费者组中的所有处理。Kafka 2.4中引入的增量协作再平衡协议已经最大限度地减少了性能影响,允许更频繁的再平衡以更好地分配每个分区上的负载。
为了增强重新分配的灵活性,分区的数量应该大于 worker 的数量。这一比率应根据应用程序而有所不同,并假设一个工作线程至少可以处理来自一个分区的负载以避免饥饿。
总结
本文从 Kafka 并行性的一般实现出发,探讨了 Kafka 实现负载均衡在现实实践中可能遇到的各种挑战,并从静态调整和动态调整两个方面给出了解决思路,特别注重讨论了动态调整策略,并分别从生产者和消费者的角度提出了解决方案。
总之,通过在 Kafka 中实现负载均衡,可以有效地将工作负载分配到可用资源之间,从而显著提高服务性能。具体的算法和策略需要根据实际情况进行选择和调整。
相关文章:

Kafka 负载均衡挑战及解决思路
本文转载自 Agoda Engineering,介绍了在实际应用中,如何应对 Kafka 负载均衡所遇到的各种挑战,并提出相应的解决思路。本文简要阐述了 Kafka 的并行性机制、常用的分区策略以及在实际操作中遇到的异构硬件、不均匀工作负载等问题。通过深入分…...

【Java面试】二十一、JVM篇(中):垃圾回收相关
文章目录 1、类加载器1.1 什么是类加载器1.2 什么是双亲委派机制 2、类装载的执行过程(类的生命周期)3、对象什么时候可以被垃圾回收器处理4、JVM垃圾回收算法4.1 标记清除算法4.2 标记整理算法4.3 复制算法 5、分代收集算法5.1 MinorGC、Mixed GC、Full…...

深入理解预处理
1.预定义符号 C语言设置了⼀些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编译的时间 __STDC__ //如果编译器遵循ANSI C&…...

DSP28335:定时器
1.定时器介绍 1.1 定时器工作原理 TMS320F28335的CPU Time有三个,分别为Timer0,Timer1,Timer2,其中Timer2是为操作系统DSP/BIOS保留的,当未移植操作系统时,可用来做普通的定时器。这三个定时器的中断信号分…...
系统架构理解
一、统一提前查好所有数据后续逻辑用到啥取啥,还是等用到对应数据的时候再查 1、用到啥查啥: 优势:减少依赖调用次数,减轻服务器压力;代码逻辑清晰,没有太多分支判断 劣势:无法避免串行调用&am…...
uni-app页面的跳转三种方式,功能作用有什么区别?
一、三种方式的作用 1、uni.reLaunch 作用是关闭所有页面,然后打开新的页面 类似于重新启动应用,打开的页面栈会被清空,只显示新打开的页面。使用uni.reLaunch方法可以实现整个应用的重定向 uni.reLaunch({url: /pages/login/login }) 2、…...

React 通信:深层传递(Props、Context、Children Jsx)
在之前的文章 探讨:围绕 props 阐述 React 通信 中总结了关于“父子”组件传值,但是当需要在组件树中深层传递参数以及需要在组件间复用相同的参数时,传递 props 就会变得很麻烦。 实际案例: 下述展示有两种状态:① 详…...

《Windows API每日一练》5.1 键盘基础
本节我们讲述关于键盘的一些基础知识。当我们按下一个键盘按键时,会产生一个键盘按键消息。这一点你能确定吗?假如是一个菜单快捷键消息,或者是一个子窗口控件消息呢?这就超出了本节讨论的范围,我们将在菜单和子窗口控…...
Class.forName()方法总结
Class.forName()方法总结 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!Class.forName()方法是Java反射机制中的一个重要方法,它用于动态加载类并返…...

Python | Leetcode Python题解之第168题Excel表列名称
题目: 题解: class Solution:def convertToTitle(self, columnNumber: int) -> str:ans list()while columnNumber > 0:columnNumber - 1ans.append(chr(columnNumber % 26 ord("A")))columnNumber // 26return "".join(an…...
【ARMv8/ARMv9 硬件加速系列 3.5.2 -- SVE 向量寄存器 有多少位数?】
文章目录 SVE 向量寄存器SVE 向量寄存器大小SVE 可伸缩性的好处SVE 寄存器长度示例SVE 向量寄存器 在 ARMv9 架构中,包括其 Scalable Vector Extension (SVE) 和 Scalable Vector Extension 2 (SVE2) 的增强,向量寄存器(通常称为 Z 寄存器)的大小设计为可伸缩的,以便在不…...
Vulkan入门系列2- 绘制三角形(未完待续)
概述: Vulkan的学习曲线是比较陡峭的,学习Vulkan刚开始像是在爬一个陡坡,等上了这个陡坡之后,后面学习曲线就相对比较平缓了。那么在Vulkan中绘制一个三角形,就相当于是在爬这样一个陡坡,因为绘制三角形需…...

企业UDP文件传输工具测速的方式(下)
在前一篇文章中,我们深入讨论了UDP传输的基本概念和镭速UDP文件传输工具如何使用命令行快速进行速度测试。现在,让我们进一步探索更为高级和灵活的方法,即通过整合镭速UDP的动态或静态库来实现网络速度的测量,以及如何利用这一过程…...

Artalk-CORS,跨域拦截问题
今天重新部署Artalk之后,遇到了CORS——跨域拦截的问题,卡了好一会记录一下。 起因 重新部署之后,浏览器一直提示CORS,之前在其他项目也遇到过类似的问题,原因就在于跨域问题。...
SSL证书怎样配置部署更安全?
在互联网上,SSL证书是用于加密网站与用户之间传输的数据的一种数字证书。它通过建立安全的连接,确保网站的身份和保护用户的隐私,是网站安全的重要组成部分。然而,要想让SSL证书发挥最大的作用,除了检查证书是否过期外…...

M1失效后,哪个是观察A股的关键新指标?
M1失效后,哪个是观察A股的关键新指标? 央地支出增速差(地方-中央支出增速的差值)或许是解释沪深300定价更有效的前瞻指标。该数值扩张,则有利于大盘指数,反之亦然,该指标从2017年至今对大盘指数…...

springboot集成积木报表,怎么将平台用户信息传递到积木报表
springboot集成积木报表后怎么将平台用户信息传递到积木报表 起因是因为需要研究在积木报表做数据筛选的时候需要拿到系统当前登录用户信息做筛选新的模块 起因是因为需要研究在积木报表做数据筛选的时候需要拿到系统当前登录用户信息做筛选 官网有详细介绍怎么集成进去的&…...

Spring Bean详解
Spring Bean作用域 默认情况下,所有的 Spring Bean 都是单例的,也就是说在整个 Spring 应用中, Bean 的实例只有一个 如果我们需要创建多个实例的对象,那么应该将 Bean 的 scope 属性定义为 prototype,如果 Spring 需…...

前端根据环境变量配置网页的title和favicon
前端根据环境变量配置网页的title和favicon 前言流程步骤一、设置environment文件二、在入口文件中配置三、删除index.html中的title和 icon link四、使用对应的打包命令进行部署 注意事项一、angular中,需要在angular.json添加favicon.ico额外的构建 前言 有些项目…...
服务器负载均衡
什么是服务器负载 1. 常见理解的平均负载 每次发现系统变慢时,我们通常做的第一件事,就是执行 top 或者 uptime 命令,来了解系统的负载情况。比如下列情况 [rootkube-node1 ~]# uptime09:44:37 up 74 days, 11:53, 1 user, load average:…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...

DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...

react菜单,动态绑定点击事件,菜单分离出去单独的js文件,Ant框架
1、菜单文件treeTop.js // 顶部菜单 import { AppstoreOutlined, SettingOutlined } from ant-design/icons; // 定义菜单项数据 const treeTop [{label: Docker管理,key: 1,icon: <AppstoreOutlined />,url:"/docker/index"},{label: 权限管理,key: 2,icon:…...