惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
T
Threatpost
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - Franky
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell
M
MIT News - Artificial intelligence
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
S
Security Affairs
P
Proofpoint News Feed
L
LINUX DO - 最新话题
宝玉的分享
宝玉的分享
S
Security @ Cisco Blogs
H
Hacker News: Front Page
Security Archives - TechRepublic
Security Archives - TechRepublic
Vercel News
Vercel News
Engineering at Meta
Engineering at Meta
Know Your Adversary
Know Your Adversary
Y
Y Combinator Blog
美团技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
月光博客
月光博客
量子位
博客园_首页
The Last Watchdog
The Last Watchdog
D
DataBreaches.Net
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed
The Register - Security
The Register - Security
Schneier on Security
Schneier on Security
H
Help Net Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Visual Studio Blog
Google DeepMind News
Google DeepMind News
F
Full Disclosure
C
Cyber Attacks, Cyber Crime and Cyber Security
MyScale Blog
MyScale Blog
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
L
Lohrmann on Cybersecurity
S
Secure Thoughts
Stack Overflow Blog
Stack Overflow Blog
Cloudbric
Cloudbric
Microsoft Security Blog
Microsoft Security Blog

XINDOO

关于内卷,几个值得深想的洞察 当创作被 Skill 化:我用 AI 写了一部 320 章的长篇网文 AI第一剑,先斩程序员 AI 也会偷懒?这个 PUA 工具专治“摸鱼式编程” Gstack 深度解析:YC CEO 开源的 AI 工程团队 GitHub Trending霸榜!深度解析AI Coding辅助神器 Superpowers 深度探讨:从 OpenClaw 爆火,看 AI Agent 的真相与程序员的未来 我复刻了NotebookLM的信息图功能 我用AI写了部小说,这里是整个过程 [翻译]我在谷歌14年学到的21堂课 2万字吊打40万字:为什么我的“牛马Agent”比“数字分身”更聪明? 最近AI领域爆火的 Agent Skills 是什么? 从计算机科学的视角来看拖延症 一周改6个库后我悟了:AI时代,程序员正在退化成“甲方” 使用n8n做一个自动同步更新的Github项目问答机器人 Agent设计模式——第 20 章:优先级排序 Agent设计模式——第 1 章:提示词链 Agent设计模式——附录 D - 使用 AgentSpace 构建 Agent Agent设计模式——第 19 章:评估和监控 Agent设计模式——第 10 章:模型上下文协议 (MCP) Agent设计模式——第 21 章:探索和发现 Agent设计模式——智能体设计模式 Agent设计模式——第 11 章:目标设定和监控 Agent设计模式——第 9 章:学习和适应 Agent设计模式——第 16 章:资源感知优化 Agent设计模式——附录 G - 编码 Agent Agent设计模式——第 13 章:人机协同 Agent设计模式——第 17 章:推理技术 Agent设计模式——附录 F - 深入剖析:Agent 推理引擎的内部运作机制 Agent设计模式——章节目录 Agent设计模式—— Agent设计模式——第 7 章:多 Agent 协作 Agent设计模式——附录 E - 命令行界面中的 AI Agent Agent设计模式——附录 C - Agentic 框架快速概览 Agent设计模式——第 3 章:并行化 Agent设计模式——**常见问题解答:Agentic 设计模式** Agent设计模式——第 14 章:知识检索(RAG) Agent设计模式——第 18 章:Guardrails/安全模式 Agent设计模式——第 15 章:Agent 间通信(A2A) Agent设计模式——第 8 章:内存管理 Agent设计模式——第 12 章:异常处理和恢复 Agent设计模式——第 4 章:反思 Agent设计模式——附录 B - AI Agentic 交互:从图形界面到现实世界环境 Agent设计模式——第 5 章:工具使用(函数调用) Agent设计模式——结论 Agent设计模式——第 6 章:规划 Agent设计模式——第 2 章:路由 从经验主义到贝叶斯理论:如何排查线上问题 我用AI为自己造了一把安全的开发者“瑞士军刀”” 从LLM和MCP的协同过程看如何做优化 打通Dify与AI工具生态:将Workflow转为MCP工具的实践 一文了解知识库背后的技术RAG AI应用的五个级别:从入门到专家的进阶之路 一文入门AI圈最近爆火的MCP协议 HTTP/3:性能改进(第 2 部分) deepseek-r1祛魅:从过度热捧到理性认知⁠ 为什么AI智能体需要工作流 如何用GPT-4o解读视频 json命令行处理神器jq介绍 OpenAI的结构化浅析 从大模型的原理到提示词优化 从经济学原理看团队分工合作 [翻译]关于人工智能的30个思考 从马斯洛需求层次理论谈职场激励 知识与智慧 如何使用大语言模型绘制专业图表 两个开源项目打造自己的大模型聚合平台 我让gpt4o给我推荐了一千多次书 得到了这些数据 用Langchain创建一个可以总结网页内容的Agent 推荐一个好用的命令行工具ShellGPT 关于ffmpeg height not divisible by 2的错误 使用Certbot解决https证书自动更新的问题 Spring Cache简明教程 软件开发中的抓大放小vs极致细节思维 OpenAI Assistants-API简明教程 OpenAI的多函数调用(Multiple Function Calling)简介 如何使用ffmpeg制作透明背景的视频 如何在地图上寻找最密集点的位置? IO密集型服务提升性能的三种方法 职场中的基本归因错误和自利归因 使用javax.validation.constraints校验参数合法性 Java Optional:让你的代码更优雅 ChatGPT函数调用初体验:让ChatGPT具备抓取网页文本的能力 如何使用ChatGPT提升自己的“码”力? 使用ffmpeg拼接两张图片 ThreadPoolExecutor——高效处理并发任务的必备良器 从CPU的视角看 多线程代码为什么那么难写! 使用ffmpeg缩小视频体积的几种方式 Linux parallel 命令使用手册 为什么说过早优化是万恶之源? Linux xargs命令介绍 深入理解Spring的事件通知机制 Java高并发之CyclicBarrier简介 聊一聊过度设计! 详解Redisson分布式限流的实现原理 Java中使用HashMap时指定初始化容量性能一定会更好吗? 如何用ffmpeg截取视频片段&截取时间不准确的坑 XINDOO的2022年年终总结 使用ffmpeg将视频转成HLS(m3u8)格式 谷歌Guava LoadingCache介绍
spring-kafka中ContainerProperties.AckMode详解
xindoo · 2023-09-16 · via XINDOO

  近期,我们线上遇到了一个性能问题,几乎快引起线上故障,后来仅仅是修改了一行代码,性能就提升了几十倍。一行代码几十倍,数据听起来很夸张,不过这是真实的数据,线上错误的配置的确有可能导致性能有数量级上的差异,等我说完我们这个性能问题你就清楚了。

  我们线上是对接了腾讯云的IOT平台,任何iot设备的上传事件都是通过腾讯云的CKafka传递给我们的,随着设备量以及事件数据量的增加,我们消费腾讯云CKafka出现了性能瓶颈,数据高峰期会有数据拥堵,从而因数据处理延迟导致业务的问题。解决最简单的方案就是扩partition和consumer,实际上半年前我们发生性能问题的时候就是这么做的,扩了一倍的partition提升了一倍的性能,然而半年后的今天又到了瓶颈。

  经过排查发现,单条kafka消息处理需要6ms,拆分所有执行逻辑后发现这6ms的延迟主要是向腾讯云发送ack的时间,我们机房到腾讯云的rtt恰好就是6ms左右,所以几乎所有的事件都耗费在消息的网络传输上面了。然而这个是受物理距离所限制,无法减减少的。后来偶然发现我们在代码中使用了spring-kafka的AckMode中的MANUAL_IMMEDIATE,这个模式下kafka的consumer会向服务端手动确认每一条消息,后来我们将这个配置调整成了AckMode.MANUAL,单条消息的处理时长从原来的6ms降低到不到0.2ms,提升了30多倍,这下即便不扩容我们的性能冗余也足够支持很多年了。 为什么简简单单改个配置就会有如此的提升? 是否还有其他的配置类型?

  实际上在spring-kafka中并不是只提供了MANUAL和MANUAL_IMMEDIATE两种ack模式,而是有以下七种,每种都有各种的作用和适合的场景。

  • RECORD:每处理一条记录后就立即进行确认。
  • BATCH:每次调用poll()方法后,只确认返回的最后一条记录。
  • TIME:每次过了设定的时间间隔后,确认最后一条在这段时间内处理的记录。
  • COUNT:每处理设定数量的记录后,确认最后一条处理的记录。
  • COUNT_TIME:组合了TIME和COUNT,即满足任意一个条件时,确认最后一条处理的记录。
  • MANUAL:用户需要手动调用acknowledgement.acknowledge()批量来确认消息。
  • MANUAL_IMMEDIATE:用户需要手动调用acknowledgement.acknowledge()来确认消息,每条消息都会确认一次。

  以上7种模式如果分类的话可以分成两种,手动确认和自动确认,其中MANUAL和MANUAL_IMMEDIATE是手动确认,其余的都是自动确认。手动确认和自动确定的核心区别就在于你是否需要在代码中显示调用Acknowledgment.acknowledge(),我们挨个来看下。

手动确认

MANUAL:

  在此模式下,消费者需要在处理完消息后手动调用Acknowledgment.acknowledge()方法来确认消息。确认操作会被批量进行,即确认操作被延迟到一批消息都处理完毕后再发送给Kafka。这种模式的优点是可以提高效率,因为减少了与Kafka服务器的交互次数。但缺点是如果一批消息消费了一半,consumer突然异常宕机,因为数据没有及时向kafka服务端确认,下次就会重复拉取到消息,导致部分数据被重复消费。

MANUAL_IMMEDIATE:

  在此模式下,消费者需要在处理完消息后手动调用Acknowledgment.acknowledge()方法来确认消息。不过,与MANUAL模式不同的是,一旦调用了acknowledge()方法,确认信息会立即发送给Kafka,而不是等待一批消息都处理完毕后再发送。这种模式可能会增加与Kafka服务器的交互次数,在网络延迟较大的情况下会出现显著的性能消费瓶颈,但可以尽快将确认信息发送给Kafka,即便是consumer异常宕机,也只是会导致单条消息被重复消费。

  手动确认的优势在于consumer可以在代码逻辑中自行判断数据是否消费成功,未消费成功的数据不确认,这样可以保证数据不丢失,手动模式可以保证数据的完整性,也就是分布式数据系统中所说的at least once。而这两种模式的核心差异就是单条确认和批量确认,批量的方式可以显著提升性能, 我在上个月的博客IO密集型服务提升性能的三种方法详细介绍过,有兴趣可以看下。

自动确认

  RECORD、BATCH、TIME、COUNT、TIME_COUNT这5种都是属于自动确认,也就是你不需要在代码中显式调用Acknowledgment.acknowledge(),只要consumer拉到消息就是自动确认,才不管是否真的消费成功,所以自动确认的模式可能会导致数据丢失,但要注意相对于手动确认,自动确认即可能导致数据丢失,也可能导致数据重复,所以它也不是at most once语义级别的。 虽然同为自动确认,但其实这5种模式还有自己的差异。

RECORD和BATCH

  首先我们先来看下RECORD、BATCH,这两种模式其实就是上文中MANUAL和MANUAL_IMMEDIATE对应的自动版本。RECORD是一条就确认一次,同样如果是在网络延迟较大的情况下也会出现性能问题。BATCH是批量确认,每次poll()后会确认这一批的消息,同样的如果consumer异常宕机也会导致未成功确认消息,从而导致消息被重复拉取到。当然如果是consumer因其他原因导致数据处理失败,但正常确认了,这种情况下会丢失消息。

TIME

  TIME模式是定时确认,比如你设置了确认时间间隔为5S,consumer就会每5s向kafka确认这5s内消费完的消息,这里有个问题是如果是高频数据流且时间间隔设置较大,可能导致堆积大量消息未被确认,然后异常宕机后重复拉取到这些消息,我们接下来要说的COUNT模式可以避免这种情况。

COUNT

  COUNT模式确认的时机是由消费数据条数触发的,比如每消费100条就确认一次,完美的避免了堆积大量未确认数据的情况。但是,如果是极低频的数据流,比如几分钟才一条数据,攒够100条得好几个小时,数据消费后长时间得不到确认,甚至可能导致kafka认为数据消费超时失败,从而导致数据被重复消费。

TIME_COUNT

  针对于TIME和COUNT的优缺点,TIME_COUNT结合了两者的特点,只要是时间间隔或者消息条数满足其一就确认,具有更强的适应性,所以当你想从TIME、COUT、TIME_COUNT三者中选一个的话,我个人觉得可以盲选TIME_COUNT,除非你特别清楚你数据的特征,知道那种更合适。

总结

  简单总结下以上几种模式,如果是不能容忍数据丢失那一定要选手动模式,如果是网络延时比较高,可以选MANUAL(批处理)的模式,但是注意即便是手动模式它也不能保证数据不重复,要想做到完全幂等还得依赖其他的方式,比如数据库事务。 如果可以接受部分数据丢失(例:监控数据),那就可以考虑自动模式了,但我个人还是不推荐RECORD模式,因为这种模式会在高网络延迟的情况下啊产生比较严重的性能问题,剩下的几种模式可以根据自己的数据量、网络情况选取,不同的情况用不同的模式可能会有明显的性能差异。