最新文章

2024年12月20日

Apache RocketMQ 荣获 2024 开源创新榜单“年度开源项目”
近日,以“新纪天工、开物焕彩——致敬开源的力量”为活动主题的“重大科技成就发布会(首场)”在国家科技传播中心成功举办,并隆重揭晓了 2024 开源创新榜单,旨在致敬中国开源力量,传播推广开源科技成就,营造中国开源创新生态。 2024 年开源创新榜单由中国科协科学技术传播中心、中国计算机学会、中国通信学会、中国科学院软件研究所共同主办,中国开发者社区承办,以王怀民院士为首组建评审委员会,进行研讨评审,面向中国开源行业领域,遴选具有创新性、贡献度和影响力的开源项目、社区、应用场景与开源事件。 在评审出的 10 个年度开源项目中,Apache RocketMQ 成功入选。 Apache RocketMQ 社区近况 Apache RocketMQ 创新论文连续被软件工程顶级会议录用 (1)2024 年 9 月,由阿里云消息队列团队发表的关于 RocketMQ 锁性能优化论文《Beyond the Bottleneck: Enhancing HighConcurrency Systems with Lock Tuning》被 CCFA 类软件工程顶级会议 FM 2024 录用。 高并发系统常常面临性能瓶颈,主要是由于线程间激烈竞争锁导致的等待和上下文切换。作为一家云计算公司,我们非常重视性能的最大化。为此,我们对轻量级自旋锁进行了改进,并提出了一种简洁的参数微调策略,能够在最低风险条件下突破系统性能瓶颈。该策略在高吞吐量消息队列系统 Apache RocketMQ 中得到了验证,实现了 X86 CPU 性能提升 37.58% 和 ARM CPU 性能提升 32.82%。此外,我们还确认了这种方法在不同代码版本和 IO 刷新策略下的一致有效性,显示出其在实际应用中的广泛适用性。这项工作不仅为解决高并发系统的性能问题提供了实用工具,还突显了形式化技术在工程问题解决中的实际价值。 (2)2023 年 9 月,由阿里云消息队列团队发表的关于 RocketMQ 高可用范式设计论文《RocketHA: A Logbased Storage High Availability Paradigm for Messaging and Streaming Scenarios》被软件工程 CCFA 类顶级会议 ASE 2023 录用。 该论文详细探讨了 RocketMQ 在其发展历程中所蕴含的高可用性设计理念,凝聚了团队在行业应用中积累的宝贵经验。为了应对分布式系统中常见的故障,如崩溃和网络分区,RocketHA 提出了一种基于日志存储的高可用性设计框架。该框架由六个基本组件构成,旨在实现系统在面对各种故障时的自动集群恢复。具体而言,RocketHA 通过模块化设计,实现了消息、事件及流场景的高可用性,确保系统能够在发生意外故障时迅速且有效地恢复。此外,该设计还优先考虑了高吞吐量与数据丢失防护,以保障系统在进行大规模数据处理时的稳定性和可靠性。评估结果表明,RocketMQ 在多种负载和故障场景下都表现出卓越的高可用性和快速恢复能力。本文提出的 RocketHA 的设计理念可为其他基于日志存储的系统提供参考和借鉴,推动相关领域的研究与开发。 GSoC(Google Summer of Code) 2024 在谷歌主办的 GSoC 2024 中,Apache RocketMQ 开源社区共提报通过两个选题: 1. RocketMQ Dashboard Supports RocketMQ 5.0 Architecture and Enhances Usability:该题目旨在强化 RocketMQ 的开源控制台能力。 2. Optimizing Lock Mechanisms in Apache RocketMQ:该题目旨在优化锁行为,优化 RocketMQ 的性能以及资源占用。 两个题目均成功结项,第一个题目为 Apache RocketMQ 发布了 rocketmqdashboard 2.0.0,自此RocketMQ Dashboard 支持 Apache RocketMQ 5.0 。第二个题目创新性地提出了 ABS 锁,为轻量化的自旋锁提供了一套退避策略,从而实现低成本、有限制的锁自旋行为,同时适应不同强度的资源争抢情况 Apache RocketMQ 社区 5.3.0、5.3.1 版本发布 Apache RocketMQ 社区近期发布了 5.3.0 和 5.3.1 两个版本,两个版本主要修复现有的 bug 并提升系统的整体稳定性和性能。值得一提的是,Apache RocketMQ 5.3.0 引入了 Apache RocketMQ ACL 2.0 支持,为用户带来了更加灵活和安全的访问控制机制。这些改进和新增功能将显著提升 Apache RocketMQ 在生产环境中的稳定性和安全性,进一步满足用户的业务需求。 Apache RocketMQ 中文社区全新升级 2024 年 7 月,Apache RocketMQ 中文社区(https://rocketmq.io)全新升级,致力于为每一位热衷于 RocketMQ 技术探索与实践的开发者,打造一个集时效性、全面性、深度于一体的一站式学习平台。 最全最新资讯: Apache RocketMQ 中文社区提供从基础到深入的全面学习资料,涵盖原理介绍、架构解读、源码分析等基础知识,高级性能使用、技术前沿探索、场景最佳实践等博客文章,用户反馈的真实答疑样例等,并及时更新版本发布、架构演进和功能迭代等社区动态,以及社区相关活动和会议信息,为您提供更多学习和交流的机会。 智能专家答疑: Apache RocketMQ 中文社区基于 Apache RocketMQ 领域专业知识库,并结合先进的大模型技术进行优化,为您提供 AI 问答助手,作为您的智能学习伴侣。通过自然语言问答,让您的疑问得到迅速解答,使您的学习之旅更加轻松有趣。 关于 Apache RocketMQ RocketMQ 致力于构建低延迟、高并发、高可用、高可靠的分布式“消息、事件、流”统一处理平台,覆盖云边端⼀体化数据处理场景,帮助企业和开发者在智能化时代,轻松构建事件驱动架构的云原生应用。 RocketMQ 自 2012 年诞生于阿里巴巴集团的核心交易链路,至今已经历十余年“双十一”的万亿级数据洪峰验证。2015 年,阿里云面向企业提供商业化的消息队列服务,其中包括云消息队列 RocketMQ 版。2016 年,阿里巴巴向 Apache 软件基金会捐赠了 RocketMQ 项目,RocketMQ 进入 Apache 孵化器。2017 年,Apache RocketMQ 成为 Apache 顶级项目,在开源消息中间件领域占据领导地位。2022 年,Apache RocketMQ 5.0 正式发布,全面拥抱云原生架构、超融合架构,进一步拓展事件驱动、物联网等场景。

2024年11月18日

基于 RocketMQ 事件驱动架构的 AI 应用实践
AI 应用在商业化服务的阶段会面临诸多挑战,比如更快的服务交付速度,更实时、精准的结果以及更人性化的体验等,传统架构限制于同步交互,无法满足上述需求,本篇文章给大家分享一下如何基于事件驱动架构应对上述挑战。 盘点 AI 应用场景 在深入探讨事件驱动架构跟 AI 结合前,我们先梳理一下 AI 应用的现状。 从应用架构层面,大致可以把 AI 应用分为以下三类: 1)基于基础模型的扩展应用,典型的如 ChatGpt(文本生成)、StableDiffusion(图像生成)、CosyVoice(声音生成)等,这类应用通常会以模型能力为核心,提供相对原子化的服务。 2)智能知识库应用,如 Langchain chatchat,这类应用是以 LLM 为核心,基于 RAG(增强检索技术)构建的具有广泛的业务场景的应用。 3)智能体应用,智能体应用核心要点是应用以 LLM 为交互中枢,能够通过工具的调用联通外部世界,复杂的表现形式如多智能体协作等,是企业 AI 应用落地最具想象空间的一类应用。 浅析 AI “原生” 说到“原生”二字,它代表的是对某种概念的广泛认知,比如提移动原生应用立马可以联想到手机端的 APP,提云原生应用很多开发者立马可以想到容器化等,而对于 AI “原生”,除了 ChatGpt,Midjourney 等几款头部 AI 应用,我们似乎还没有看到像移动应用那样广泛的“原生”应用被定义出来,当然今天也没有办法给出明确的结论,只是通过一些事实,帮大家推演 AI “原生”的方向,希望能够帮助慢慢凝聚在内心中那个对“AI 原生”的影像。 AI 给应用架构带来的变化 当 AI 能力加入后,我们的应用架构发生了较大的变化。RAG,Agent 等编程范式被引入,传统的工作流也因为有了 AI 节点,变得与以往有所不同。 AI 应用架构RAG AI 应用架构Agent 加入 AI 节点的工作流 AI 应用的变化趋势 从观察知名 AI 厂商的产品形态演进看,AI 应用由前面提到的基础模型扩展、智能知识库、智能体三类叠加又相对分离,在慢慢向由智能体统一管控约束的方向发展。 比如 Open AI 的 Canvas,Claude Artifacts,Vercel v0 等产品特性。它们都表现出了一系列的共性:智能内核,多模态,LUI 交互。 从另外一个角度理解,AI 原生的应用只有突破之前的用户体验才有可能让用户买单。分散的基础模型能力,多模态能力都只能在某些场景下有体验提升,某些方面甚至不如传统应用的用户体验。所以需要整合,将对话式交互,智能模型和多模态叠加从而构建出超越传统应用的使用体验。 使用事件驱动构建 AI 原生 这里并不是单纯为了追求技术的先进性而使用事件驱动架构,是因为实践中顺序式的架构有时候无法满足业务需求。 传统顺序式的架构在构建 AI 原生的挑战 顺序调用无法保障推理体验 模型服务的推理耗时远高于传统意义的网络服务调用,比如在文生图这个场景下使用 StableDiffusion 服务,即使经过算法优化后最快也是秒级,并发量较大的时候,会很容易导致服务器宕机。此外如声音的合成,数字人的合成等耗时可能是分钟级的,此时顺序调用明显就不太合适。选择事件驱动的架构可以快速响应用户,推理服务按需执行,这样既能够保障用户体验,同时也降低系统宕机风险。 顺序调用无法支持实时数据构建的需求 在智能问答系统中,结果的好坏跟数据有很大的关系。问答召回数据的实时性和准确性很大程度影响着智能问答系统的用户体验,从系统架构层面,问答和数据的更新是分开的。靠人工去更新海量数据不现实,通过设置定时任务以及构建知识库数据更新的工作流能够更加有效的解决数据实时更新的问题,事件驱动架构在这个场景下优势非常明显。 双向互动场景无法实现 在问答服务场景下,拟人化的行为能够得到用户好感从而扩展商机,传统的问答式应用架构相对机械死板,而使用消息队列作为信息传输可以有效主动触达用户,通过合理的意图判断,主动向用户问好,是有效的留存手段。 事件驱动构建 AI 原生的实践 接下来分享一下基于事件驱动架构构建的 AI 应用的一些实践。 StableDiffusion 异步推理 前面提到了关于文生图模型 StableDiffusion 在服务客户中遇到的问题,我们利用事件驱动架构,使用函数计算和轻量消息队列(原 MNS)构建了 StableDiffusion 的异步推理架构,用户请求到来时经过函数计算网关到达 API 代理函数,API 代理函数对请求进行打标鉴权,之后将请求发送到 MNS 队列,同时记录请求的元数据和推理信息到表格存储 TableStore,推理函数根据任务队列进行消费,调度 GPU 实例启动 StableDiffusion 进行服务,结束后返回图片结果以及更新请求状态,端侧通过页面上的轮询告知用户。 VoiceAgent 实时对话 这是一个相对复杂的应用,使用者可以通过语音跟背后的智能问答服务实时对话,同时还能够接收到来自智能服务的主动询问。 整体依然采用事件驱动架构,其 RTC Server 部分安装 rocketmqclient,订阅中心化的服务 topic,由定时任务(主要是意图分析)触发向队列 topic 生产消息内容,然后由 rocketmqclient 消费,进行主动询问。 VoiceAgent 知识库实时数据流 对于问答的另外一端,知识库的自动更新,则是通过 Catch Data Capture 策略,比如由外部系统数据源触发,或者通过将文档上传 OSS 触发。数据经过切片,向量化之后存储到向量数据库以及全文检索数据库。 面向 AI 原生应用的事件驱动架构 最后分享一下作为 AI 应用开发者的一套组合方案:通过 阿里云云应用平台 CAP(Cloud Application Platform) 选出基础模型服务,如 Ollama,ComfyUI,Cosyvoice,Embedding 等进行快速托管,使用 RcoketMQ,Kafka,MNS, Eventbridge 等搭建数据流管道和消息中心,本地利用 Spring AI Alibaba 等框架开发后端服务,实现 RAG,Agent 等能力。前端使用 Nextjs 框架构建界面,之后将开发好的前后端通过 Serverless Devs 工具部署到 CAP 平台,进行线上调用访问,最终上生产采用云原生网关保驾护航,对于长期的知识库或者智能体的运维则通过 ARMS 进行指标监控。

2024年11月6日

RocketMQ 打破锁性能瓶颈之道
背景 Apache RocketMQ 是一个云原生消息传递和流式处理平台,可简化创建事件驱动型应用程序的过程。多年来随着 RocketMQ 的迭代,已经编写了大量代码来利用多核处理器,通过并发提高程序效率。因此管理并发性能变得至关重要,同时锁对于确保在访问共享资源时多个执行线程安全同步至关重要。尽管锁对于确保多核系统中的互斥性是必不可少的,但它们的使用也可能带来优化挑战。随着并发系统内部变得越来越复杂,部署有效的锁管理策略是保持性能的关键。 因此,在 GSOC 2024 中,我们 Apache RocketMQ 开源社区提报了一个非常具有挑战性的题目:《GSOC269 : Optimizing Lock Mechanisms in Apache RocketMQ》。在这个题目中,我们旨在优化锁行为,优化 RocketMQ 的性能以及资源占用。通过这个题目,我们创新性地提出了 ABS 锁 —— Adaptive Backoff Spin Lock。ABS 锁的思想是通过为轻量化的自旋锁提供一套退避策略,从而实现低成本、有限制的锁自旋行为,同时适应不同强度的资源争抢情况。 之所以取其缩写 ABS,是因为该锁的设计思想与刹车系统中的 ABS 系统有一定相似性。在早期系统中使用的自旋锁会一直进行自旋,但是当临界区较大时会产生大量无效自旋,类似刹车制动中的“抱死”结果,这导致我们的资源利用急剧增长。为了避免这种资源损耗,当前社区使用互斥锁对其进行了替代,避免临界区较大时的资源浪费。但是在这种替代方案落实后,当消息较小时,互斥锁的阻塞唤醒机制反而影响到消息发送的响应时间,并带来了更高的 CPU 损耗。 由于自旋锁在临界区较小时的响应时间(RT)以及 CPU 利用方面都有较好的表现,唯一的不足是在资源争抢时会带来资源浪费。因此我们决定对自旋锁进行优化,降低无效的资源损耗,从而更好的利用自旋锁的优点,使其同时适合争抢激烈或不激烈的场景。在实践中,我们已经证明了调整锁策略会影响 RocketMQ 的消息发送性能,带来显著的性能优化结果。 通过 ABS 锁,我们还能解决开源使用者对锁的抉择问题:在 RocketMQ 消息投递时存在两种锁定机制,SpinLock(swapAndSet),以及 ReentrantLock 互斥锁,但并无文档对其进行分析使用的场景。所以我们通过 ABS 锁对其进行整合,达到最优状态并且完成服务端的锁定机制闭环,不需要用户去决定当前场景锁定机制的选取,自然而然地根据争抢情况对锁参数进行微调。ABS 锁可以根据运行时条件动态调整其行为,例如锁争用级别和争用同一资源的线程数。这可以通过最大限度地减少与锁获取和释放相关的开销来提高性能,尤其是在高争用的情况下。通过实时监控系统的性能指标,ABS 锁可以在不同的锁定策略之间切换。 我们目前已经实现自适应锁定机制(ABS 锁),通过实验结果成功验证:自适应锁定机制达到不同场景下单独使用互斥锁/自旋锁的最优效果,简而言之就是取得不同场景下最优锁定机制的效果。本文将详细介绍 Apache RocketMQ 的锁机制迭代过程,并介绍 ABS 锁的优化效果。 相关概念介绍 在文章正式开始前,需要介绍一些本文中可能频繁用到的概念:临界区、互斥锁、自旋锁。了解清楚这些概念将有助于阅读本文的优化思想。 临界区 临界区(Critical Section)是一段供线程独占式访问的代码,也就是说若有一线程正在访问该代码段,其它线程想要访问,只能等待当前线程离开该代码段方可进入,这样保证了线程安全。一般临界区大小是受多方面影响的,例如,本文中消息发送过程的临界区大小可能受消息体大小影响。 互斥锁 互斥锁是一种独占锁,当线程 A 加锁成功后,此时互斥锁已经被线程 A 独占了,只要线程 A 没有释放手中的锁,线程 B 就会失败,就会释放掉 CPU 给其他线程,线程 B 加锁的代码就会被阻塞。 互斥锁加锁失败而阻塞是由操作系统内核实现的,当加锁失败后,内核将线程置为睡眠状态,等到锁被释放后,内核会在合适的时机唤醒线程,当这个线程加锁成功后就可以继续执行。具体的互斥锁行为可以参考下图: 互斥锁带来的性能开销主要在两次线程上下文切换的成本。 1. 当线程加锁失败时,内核将线程的状态从【运行】切换到睡眠状态,然后把CPU切换给其他线程运行; 2. 当锁被释放时,之前睡眠状态的线程会变成就绪状态,然后内核就会在合适的时间把CPU切换给该线程运行。 自旋锁 自旋锁通过 CPU 提供的原子操作 CAS(CompareAndSet),在用户态完成加锁和解锁操作,不会主动产生线程上下文切换,所以相比互斥锁来说,会快一些开销小一些。它和互斥锁的主要区别在于,当加锁失败,互斥锁使用线程切换应对,而自旋锁用忙等待应对。 RocketMQ 的锁机制迭代 下面,我们将介绍 RocketMQ 的锁机制迭代过程。由于自旋锁、互斥锁有各自的优劣势:自旋锁的优势在于其轻量级和低上下文切换开销,适合短时间等待的情况;而互斥锁的优势在于能够节约资源,适合长时间占有锁的场景。 因此本文中将其优势分别比喻为“鱼”和“熊掌”,我们将一步步介绍如何同时拿到最优质的“鱼”和“熊掌”。 鱼和熊掌的抉择——互斥/自旋 在早期为了减小线程上下文切换带来的资源损耗,Apache RocketMQ 选取了自旋锁进行实现。随着版本迭代 RocketMQ 的并发压力日益增长,导致当临界区较大时,自旋锁会产生大量无效自旋,这导致 Broker 的资源利用急剧增长。因此后期 RocketMQ 又使用互斥锁对其进行了替代,避免临界区较大时的资源浪费。 但是当消息较小时,互斥锁的阻塞唤醒机制反而影响到 RT 以及上下文切换引起的更高的 CPU 损耗,自旋锁在临界区较小时的响应时间(RT)以及 CPU 利用方面都有较好的表现,因此在过去我们一直被锁定机制的正确选取所困扰。直到今日,RocketMQ 的内部仍然保留着这两种锁,且通过一个开关进行控制:useReentrantLockWhenPutMessage。 这意味着,使用者需要在启动 broker 时,决定自己的锁类型——如果消息体都比较小,且发送 TPS 并不大,则使用自旋锁;当消息体较大时,或者竞争极为激烈时,则启用互斥锁。 鱼和熊掌兼得—— k 次退避锁 为了解决这个问题,我们启动了锁优化的工作。我们希望有一把锁能够同时具备自旋锁、互斥锁的特点,同时适用于竞争激烈和不激烈的情况。我们最终决定改造自旋锁,通过一把特殊的自旋锁,使系统在各种竞争情况下都保持非常优质的锁行为。自旋锁由于无限自旋直到获取到锁,在临界区较大时会产生较多的空转,耗费大量的 CPU 资源。为了能有效利用自旋锁的优势,因此我们要在临界区较大时对其空转次数的控制,从而避免大量空转,最大程度兼容临界区较大的场景。 最终我们通过对自旋锁的行为建模,提出了 k 次退避锁:进行 K 次自旋后还未获得锁后,执行 Thread.yield() 将 CPU 执行权交给操作系统。这种行为能够避免互斥锁的无谓上下文切换,也能避免高压场景下的无限自旋带来的 CPU 损耗。 这种行为能够缓解系统压力,取得自旋和 CPU 上下文切换两中方法中的最低资源损耗。 在刚过去不久的 FM 24 会议上,Juntao Ji 已经做出 k 次自旋锁的相关理论建模分享,以及实验验证[3]。在k次自旋锁的作用下,我们能找到系统性能的局部最优点,达到最大的 tps 性能。结果如下表所示: 以 X86 架构,同步刷盘的行为为例。实验结果表明,在 k= 10^3 时,发送速度不仅达到峰值(155019.20),CPU 使用率也达到最低。这表明退避策略成功地节省了 CPU 资源。此时,CPU 支持更高的性能水平和较低的利用率水平,这表明性能瓶颈已经转移——例如,可能已经转移到了磁盘上。在表中可以观察到,在具有相同的 k(10^3)和配置参数(最新代码,SYNC 刷盘模式)的 ARM CPU 上,RocketMQ 的性能提高了 10.4%。此外,如上图所示,当 k= 10^3 时,CPU 使用量大幅下降,从平均超过 1000% 下降到 750% 左右。资源消耗的减少表明,减轻其他系统瓶颈可能会导致更显著的性能提高。 最优质的鱼和熊掌—— ABS 锁 在上文已经证明了 k 次退避锁的有效性。但是当前还有一个问题:我们发现当临界区足够大时,自旋锁的资源损耗依旧远超互斥锁(多次退避仍然获取不到)。这样 k 值其实带来的影响是负面的,也就是说,最终逃避不了上下文切换的成本,反而还带来了自旋的等待成本。 因此我们决定通过实现 k 的动态调整再次优化,当临界区较大时,对k进行自适应增大,当达到与互斥锁相同级别资源损耗时(即 k 达到自适应的最大值),此时自旋锁已经不再适合此种场景,因此我们将对其进行互斥锁的切换。这也是我们最终要实现的 ABS 锁。 1. ABS 锁实现 我们通过对不同的锁定机制进行理论分析其所适合的场景,并对其在所适合的场景进行大量实验测试得出多个场景的最优锁定机制。最后通过对运行时条件的动态变化(竞争线程数/TPS/消息大小/临界区大小)进行最优锁定机制的切换。 2. ABS 锁的 K 值自适应策略 上面我们论证出控制自旋次数对于性能优化有不错的效果,但是这个 K 值对于不同系统是不一样的,因此我们需要实现自旋次数 K 的自适应。 简而言之,K 的自适应策略就是一种从低频次自旋到高频次自旋的演化过程,对应临界区争抢变得不断严重或是临界区不断变大的过程。当 k 逐渐增大的过程中,可以增加在线程退避之前就获取到锁的概率,但是当自旋次数增加到一定数量级时,此时自旋成本已经高于线程上下文切换的成本,说明此时已经不适合使用自旋锁——所以此时退化为互斥锁。 通过实验,我们将自旋次数 K 自适应最大值设置为1万,因为在实验中,我们发现当自旋次数大于1万时,竞争激烈时带来的优化效果会受到显著影响,甚至大于一次 CPU 上下文切换的代价。所以此时我们将其切换为互斥阻塞等待锁定机制。 为了自适应调整 K 值,我们提出了一个闭环的工作流,如下图所示: 在图中我们可以看到,我们主要衡量当前 k 值下,自旋获取锁的成功率。如果在当前 k 值下获取锁的成功率不够高,则适当增加 k 值,这将带来更大的获取概率。但是如果一直增加都无法有效提高拿锁成功率,则将其转为互斥锁,会带来更高的效益。 成为互斥锁代表当前可能有较高的突发流量,导致对锁的竞争变得激烈了。但是互斥锁是不适用于低压场景的,所以我们还需要决定如何从互斥锁转回自旋锁。因此我们记录了从自旋锁切换为互斥锁的请求速率。当整体请求速率低于这个数值的 80% 时,则切换回自旋锁。 实验及结果 为了验证 ABS 锁的正确性以及性能优化效果,我们做了多组实验,包括性能测试以及混沌故障测试。本章将介绍具体的实验设计以及结果。 1. 性能实验配置 1. namesrv 一台,broker一台,openmessagebenchmark 一台压测机 2. 上述三台机器的配置为,处理器:8 vCPU,内存:16 GiB,规格族:ecs.c7.2xlarge,公网带宽:5Mbps,内网带宽:5/ 最高 10 Gbps。 3. 消息体大小分别设置了1KB以及2B两种场景,用于影响发送消息时的临界区大小。 2. 性能测试结果 CPU 与耗时的优化 消息 body 大小 1 kb 时,我们记录了不同消息发送速率下的 CPU 占用情况。结果如下图所示: 结果表明,在消息量不断增加时,我们的自适应锁带来了非常明显的优势,有效降低了 CPU 的使用率。 另外,我们还对消息发送时的 P9999 做了记录。P9999 代表发送过程中,发送耗时排在 99.99% 的尾部请求,一般反映了这段时间内的最慢请求速度。结果如下图所示: 可以看到,在不同 TPS 下,我们的自适应锁都能带来更优质的 P9999,有效降低了发送过程中由于锁争抢带来的耗时。 不过,尾部的请求情况一般代表竞争极为激烈时的极端场景。可能有的消息经过多次锁请求尝试但是都未获得锁,因此导致了这种长尾效应。我们还测试了在不同 TPS 下的平均发送耗时情况,发现在竞争极为严重时,我们的 ABS 锁由于自带了一定自旋,所以会让平均延时大约提升 0.5 ms。使用时需要仔细衡量具体场景,以确定是否在高压时开启自适应锁。 我们同时还针对消息体更小的实验场景做了实验,下表是完整的测试结果: 最大性能提升 此外,为了计算由自适应锁带来的性能提升,我们还测试了 Broker 的最大性能,结果如下所示: | CPU Arch | Flush Policy | Original QPS | Optimal QPS | Improvement | | | | | | | | X86 | ASYNC | 176312.35 | 184214.98 | +4.47% | | X86 | SYNC | 177403.12 | 187215.47 | +5.56% | | ARM | ASYNC | 185321.49 | 206431.82 | +11.44% | | ARM | SYNC | 188312.17 | 212314.43 | +12.85% | 根据该表,我们可以认为自适应锁同时能够在多个场景下均找到最大的性能点,实现性能的释放。 实验总结 经过如上所有实验数据,我们可以得出如下结论: 1. 在临界区较小时,ABS 锁提供更高的 TPS 以及更低的响应延时,极限 TPS 提高 12.85% 甚至更高,极限 TPS 下响应时间降低了 50% 左右; 2. 在临界区较大时,ABS 锁提供更低的 RT 以及更低的资源损耗,CPU 损耗从 500%400%,减少无效资源浪费。 3. 故障测试 在软件工程领域,提倡"拥抱故障"的理念意味着认识到错误和异常是正常的一部分,而非完全避免。像 RocketMQ 这样的关键系统,它在生产环境中承受的压力远超于理想化的实验室测试。为此,采用了混沌工程策略,这是一种主动探寻系统极限和脆弱性的实践。 混沌工程的核心目标是增强系统的鲁棒性和容错能力,它是通过在实际操作中人为制造故障,如网络延迟、资源限制等,来观察系统如何应对突发状况。这样做是为了确认系统是否能在不确定和复杂的现实中保持稳定,能否在面对真实世界的问题时依然能高效运作。 RocketMQ 引入自适应锁定机制后,进行了严格的混沌工程实验,包括但不限于模拟分布式节点间的通信故障、负载峰值等情况,目的是验证新机制在压力下的性能和恢复能力。只有当系统经受住这种高强度的“拷打”测试,证明它能在不断变化的环境中维持高可用性,我们才认为这是一个成熟的、可靠的解决方案。 总结起来,通过混沌工程,我们对 RocketMQ 进行了实战演练,以此来衡量其实现高可用性的真正实力。 并希望通过这样的故障测试,证明我们对锁的调整不影响其数据写入的正确性。 实验配置 我们混沌测试的验证实验环境如下: 1. namesrv 一台,内含 namesrv 进程。 2. openchaos 的混沌测试一台,向 broker 发出控制指令。 3. broker 三台,同属一个集群,内含 broker 进程。 上述五台机器的配置为,处理器:8 vCPU,内存:16 GiB,规格族:ecs.c7.2xlarge,公网带宽:5Mbps,内网带宽:5/ 最高 10 Gbps。 在测试中,我们设置了如下的若干种随机测试场景,每种场景都会持续至少 30 秒,且恢复后会保证 30 秒的时间间隔再注入下一次故障: 1. 机器宕机,这个混沌故障注入通过 kill 9 命令实现,将会杀死范围内的随机进程。 2. 机器夯机,这个混沌故障注入通过kill SIGSTOP 命令实现,模拟进程暂停的情况。 每组场景的测试至少重复 5 次,每次至少持续 60 分钟。 实验结论 针对上述提出的所有场景,混沌测试的总时长至少有: 2(场景数) 5(每组测试次数) 60(单组时长) = 600分钟 由于设置的注入时长 30s,恢复时长 30s,因此至少共计注入故障 600/1 = 600 次(实际上注入时长、注入次数远多于上述统计值)。 在这些记录在册的测试结果中,RocketMQ 无消息丢失,数据在故障注入前后均保持强一致。 总结 本文实现了 RocketMQ 锁定机制的迭代过程以及自适应退避自旋锁机制(ABS 锁)的设计以及实现,随着并发系统内部变得越来越复杂,部署有效的锁管理策略是保持性能的关键。因此,我们希望更深入地探索该领域性能优化的潜力,探索性能的极限。 同时我们希望在未来结合多种分布式锁定机制以及其他优秀思想,对其进行实现以及性能测试,期待达到多端本地锁定状态共识:单次通信即可得到锁的成果,减少无效网络通信以及更低的总线资源损耗。但目前专注于消息投递时的锁定机制实现,并未对其进行具体实现以及测试。其它分布式锁机制可以参考如下。 未来可能引入的其它锁优化思想 延迟槽位思想(Delay card slot idea): 对每个客户端分配不同槽位的延时,让客户端进行延迟后再次请求,从而避免总线的大量无效碰撞。 CLH 思想: 循环读取上一个位点的值,更改自身状态。 MCS 思想: 与 CLH 相似,但是时在本地自旋,更改下一个节点的状态。解决了 CLH 在 NUMA 系统架构中获取 locked 域状态内存过远的问题 SMP CPU 架构 基于 Ppersistent CSMA 思想: Ppersistent CSMA(Persistent Carrier Sense Multiple Access)是一种网络通信协议的思想,它通常用于描述分布式环境中如无线局域网(WiFi)中的冲突避免策略。这个思想起源于 CSMA/CD(Carrier Sense Multiple Access with Collision Detection)协议,但它引入了一种更持久的监听机制。 1. 基本流程: 每个设备(节点)在发送数据前会持续监听信道是否空闲。如果信道忙,节点就会等待一段时间后再次尝试。 2. P计数器: 当检测到信道忙时,节点不会立即退回到等待状态,而是启动一个名为 P(persistent period)的计数器。计数器结束后,再尝试发送。 3. 碰撞处理: 如果有多个节点同时开始发送,在信道上发生碰撞,所有参与碰撞的节点都会注意到并增加各自的P计数器后再试。这使得试图发送的数据包在更长的时间内有机会通过,提高了整体效率。 4. 恢复阶段: 当 P 计数器归零后,如果信道依然繁忙,节点会进入恢复阶段,选择一个新的随机延迟时间后再次尝试。 Ppersistent CSMA 通过这种设计减少不必要的冲突次数,但可能会导致网络拥塞情况下的长时间空闲等待。 参考链接 [1] Apache RocketMQ [2] OpenMessaging OpenChaos [3] Ji, Juntao & Gu, Yinyou & Fu, Yubao & Lin, Qingshan. (2024). Beyond the Bottleneck: Enhancing HighConcurrency Systems with Lock Tuning. 10.1007/9783031711770_20. [4] Chaos Engineering [5] T. E. Anderson, "The performance of spin lock alternatives for sharedmoney multiprocessors," in IEEE Transactions on Parallel and Distributed Systems, vol. 1, no. 1, pp. 616, Jan. 1990, doi: 10.1109/71.80120 [6] Y. Woo, S. Kim, C. Kim and E. Seo, "Catnap: A Backoff Scheme for Kernel Spinlocks in ManyCore Systems," in IEEE Access, vol. 8, pp. 2984229856, 2020, doi: 10.1109/ACCESS.2020.2970998 [7] L. Li, P. Wagner, A. Mayer, T. Wild and A. Herkersdorf, "A nonintrusive, operating system independent spinlock profiler for embedded multicore systems," Design, Automation & Test in Europe Conference & Exhibition (DATE), 2017, Lausanne, Switzerland, 2017, pp. 322325, doi: 10.23919/DATE.2017.7927009. [8] OpenMessaging benchmark
查看全部文章
ABOUT US
Apache RocketMQ事件驱动架构全景图
微服务
Higress
Dubbo
Sentinel
Seata
Spring Cloud
Nacos
物联网
家电
汽车
穿戴设备
充电桩
工业设备
手机
事件驱动架构平台
RabbitMQ
Kafka
EventBridge
MQTT
RocketMQ
MNS
Apache RocketMQ as Core
计算
模型服务
函数计算
容器
存储
对象存储
数据库
NoSQL
分析
Flink
Spark
Elastic Search
事件
云服务器
对象存储
云监控
SaaS事件
通知
语音
短信
邮箱
移动推送

产品特点

为什么学习 RocketMQ

云原生
生于云,长于云,无限弹性扩缩,K8S 友好
高吞吐
万亿级吞吐保证,同时满足微服务于大数据场景
流处理
提供轻量、高扩展、高性能和丰富功能的流计算引擎
金融级
金融级的稳定性,广泛用于交易核心链路
架构极简
零外部依赖,Shared-nothing 架构
生态友好
无缝对接微服务、实时计算、数据湖等周边生态
浙ICP备12022327号-1120