热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

快手RocketMQ高性能实践

本文作者:黄理,快手在线消息系统负责人。快手对于RocketMQ社区版本的优化一般为在其外层进行能力的构建,而不是对其内部进行大改动,因为内部大改不利于后期的版本升级。即使对内部R

1.png

本文作者:黄理,快手在线消息系统负责人。

快手对于 RocketMQ 社区版本的优化一般为在其外层进行能力的构建,而不是对其内部进行大改动,因为内部大改不利于后期的版本升级。即使对内部 RocketMQ 进行了修改,我们也会尽量通过 PR 将新特性回馈到社区。

快手会定期对 RocketMQ 进行升级。2022年春节,我们大胆使用了尚未正式发布的 RocketMQ 4.9.3-SNAPSHOT 版本,平稳度过了快手一年中最重要的活动,这也证实了社区版本 RocketMQ 的兼容性和稳定性。


应用篇

2.png

RocketMQ 进入快手两年内,从 0 发展到每天数千亿消息级别。快手是 RocketMQ 社区版本的事务消息最早的大规模用户,目前每天有百亿以上的事务消息和定时消息,实现了跨 IDC的自动负载均衡以及容灾,实现了多级泳道(项目)互不干扰,多个项目可同时开发,以及可回落。

3.png

RocketMQ的落地方式一般为两种。

方式一:在开源软件的基础上进行修改,能够快速轻松地实现需要的功能,但后续升级存在很大不便。

方式二:对RocketMQ的 client 和 server 只进行少量修改。如果 server 存在能力缺失,会开发辅助的 server 或以 proxy 进行补充。我们在 client 之上包装了一层 MQ SDK,对用户屏蔽了具体实现。快手也是基于此方式对RocketMQ进行了落地。

4.png

MQ SDK如上图,分为三层:最上层为 API ,用户与该层打交道;中间为核心层,能够实现各种通用的能力;最底层负责与具体的 MQ 交互,当前只有 RocketMQ 的实现,但未来也许会有其他消息中间件的实现。

中间层实现了热变更的能力。用户配置不写在代码里,而是在平台进行指定,指定以后热生效,SDK 会直接加载新的配置并自动 reload 用户程序,无需重启。

5.png

RocketMQ 会分配 Logic topic,业务代码无需关心集群在哪,无需关心当前环境,也无需关心数据标记比如压测、泳道,只需使用我们提供的非常简单的 API ,复杂的过程全部在核心层进行封装,对业务用户屏蔽。

6.jpeg

上图为跨机房负载均衡的实现流程。

所有Logic topic 都会映射到上图中间的两个机房,每个机房部署一个集群。RocketMQ 集群可以有多个 broker ,生产者和消费者对 broker 有故障感知和转移能力,能够通过 NameServer 发现哪个 broker 故障以避免与其进行连接。为了实现更好的控制,我们在集群之上又封装了一层负载均衡,并在 client 端实现。

每一个 Logic topic 都被分配到两个集群,生产者在生产时会同时连接到两个集群。两个集群分别位于不同 IDC,同一地区的两个IDC之间延时大约为1-2ms。消费者侧也是双连,一旦某机房或集群发生故障,流量会立刻自动转移到另一机房。

我们将生产端的自动负载均衡(自动failover)进行了抽象封装,做成了开源项目。Failover 组件与 RocketMQ 无关,在主调方做 RPC 或消息生产等调用时,会检查被调方的健康度。如果被调方不健康或响应很慢,则会调低其权重。

扫描上方二维码,了解更多关于该组件的功能。

7.png

RocketMQ 实现了简单的延迟消息,但是只能实现几个固定级别的延时,而实际的业务更希望发消息时可以任意指定延迟时间。因此我们通过外挂 Delay Server 的方式实现了任意精度的延迟消息。

Delay Server 会将用户要求延迟投递的消息进行保存,等到指定时间以后,再将消息送回原来的业务 topic 。

8.jpeg

基于PULL的模式(RocketMQ的PUSH Consumer也是基于PULL),很难直接实现动态的多泳道隔离。因此很多公司会选择根据泳道的不同将消息投递到不同的 topic,这样虽然实现了功能,但是侵入性太强,并且也不好实现多级回落。

而在快手,我们将所有泳道的消费都放在同一个 topic 里,并且实现了多级泳道回落。比如项目 A 和项目 B 同时在开发,项目 A 生产的消息由项目 A 的消费者消费。项目 A 下面有子项目A.X和A.Y,那么A.X生产的消息由A.X的消费者消费,但是如果A.Y没有消费者,因此A.Y生产的消息会回落到由 A 的消费者进行消费。

9.jpeg

快手的泳道隔离主要通过 RPC 转发实现。

如上图,黄色线代表项目 A 的数据流向,橙色线代表项目 B 的数据流向。SDK 会在将数据交给业务用户之前,先检查数据的泳道标记是否匹配,如果不匹配,则会通过 RPC 的方式转发至匹配的消费者。

这样我们等于是将 PULL 转为了 PUSH,在主调方进行选择,所以能够将所有项目放在同一个 topic 里,且能够实现隔离。

10.png

RocketMQ 是基于 queue 来进行客户端的 rebanance,如果消费者的数量大于queue,则会导致部分消费者无事可做;或有时 queue 分配不均匀,导致部分消费者负担大、部分消费者负担小。

我们通过RPC的方式实现了消费 Proxy,先从 RocketMQ 的 broker 消费数据,再通过 RPC 的方式  PUSH 到 consumer。

消费 proxy 的 RPC 与前文的 RPC 转发使用同一套机制,因此RocketMQ 不需要过多的 queue, 但可以有很多消费者。消费 proxy 为可选项,只需在平台指定消费方式,无需修改代码也无需重启,即可直接热生效。

11.jpeg

此外,我们开发了拨测程序,生成了一个模拟的生产者和消费者。生产者会往线上所有集群的每一个 broker 发送消息,包括普通消息、定时消息和事务消息。消费者消费到消息后,会取出消息体内生产者的 IP 地址,然后通过 TCP 的方式 ACK 回生产者,告知生产者消息是否丢失、是否重复以及从生产到消费的延迟是多少。

另外,还可以针对生产者和消费者进行各种配置,比如消息体大小、生产速率、对账抽样比例、对账周期等。比如在配置中将速率调大,即可实现压测,生产者和消费者会进行打点,最终可在 Grafana 上进行查看和告警。


性能篇

对 RocketMQ 进行性能优化后,300字节小消息生产 TPS 提升54%,同时 CPU占用降低11%;600 queue消费性能提升200%,跨IDC 100KB大消息单线程生产 TPS 提升693%,跨IDC 100KB集群消费吞吐提升250%。

优化主要分为两批。

12.png

第一批优化集中在RocketMQ4.9.1版本,包括清除多余的日志、消除不必要的锁、消除主从复制中的数组拷贝、优化Broker的默认参数、优化锁内操作的性能并将部分操作抽取到锁外、优化消息属性编解码的性能以及优化消息Header解析的性能。扫描二维码可阅读本次优化相关的完整文章。

另外,RocketMQ 4.9.0版本的默认参数设置不合理,因此我们在4.9.1版本对其进行了优化,使得性能有了巨大提升。

13.png

上图为第二批优化的目标:



  • 降低 CPU 开销。RocketMQ 不消耗 CPU,但是在混合部署场景下,CPU 极有可能会成为问题,因此需要对 CPU 开销进行优化。



  • 提升跨机房的生产、消费的吞吐。



  • 提升大消息的吞吐。



  • 提升queue特别多的场景下的消费性能。



第二批优化大部分集中在社区的ISSUE3585 里,扫描上方二维码可阅读完整文章。

14.png

上图为第二批优化CPU 方面的具体内容,字母编号与 ISSUE3585 相对应。此前RocketMQ 使用 Fastjson 做序列化,而有一个自定义的协议性能略微优于 Fastjson,我们对其进行了深入研究和优化,最终使得 RocketMQ 在编解码上性能也得到了很大提升。

15.png

RocketMQ 构建 Queue 的程序为单线程,因此我们使用mmap buffer 代替 FileChannel,性能得到了极大提高。

上图红框中为某方法优化前后对比。

16.png

此外,我们将 Pull 通知移动到另外的线程,使其不占用线程的资源。同时,将通知自动聚批,兼顾高吞吐和低延迟,只有 TPS 较高时才会自动打开,阈值可设置,避免 Pull 通知在 Broker 和消费者之间震荡频率过高,消耗 CPU。

17.png

大消息性能不佳也是一直以来很大的困扰,经过分析我们发现 RocketMQ remoting 的 TCP 参数设置有待优化。原先的buffer 设置为固定值,当机房延迟很大时,过小的 buffer 会导致 TCP 连接的吞吐受到严重影响。因此,我们将 buffer 修改为由操作系统自动管理,以保证吞吐。

上图列出了线上实测的数据表,可以看出消费的性能提升了数倍。

18.png

在极高的 TPS 场景下,如果消息体较大,则操作系统内存分配可能会成为 RocketMQ 的瓶颈,4.X 的内核下的表现远远优于 3 .X 。极端场景下,3.X内核通常需要将参数 min_free_kbytes 调至较大值。

19.png

我们于2021年12月社区开发者会议现场演示了性能测试,对比了第二批优化前后的4.9.2版本和4.9.3 Snapshot版本(包括当时还未合并进该版本的B和K的优化)的性能。

测试时,在电脑上同时运行所有 broker、生产者、消费者。老版本TPS不到 3w,而新版本有了自动聚批的能力,TPS 可达 6 w,相比于老版本提升了一倍。


加入 Apache RocketMQ 社区

十年铸剑,Apache RocketMQ 的成长离不开全球接近 500 位开发者的积极参与贡献,相信在下个版本你就是 Apache RocketMQ 的贡献者,在社区不仅可以结识社区大牛,提升技术水平,也可以提升个人影响力,促进自身成长。

社区 5.0 版本正在进行着如火如荼的开发,另外还有接近 30 个 SIG(兴趣小组)等你加​入,欢迎立志打造世界级分布式系统的同学加入社区,添加社区开发者微信:rocketmq666 即可进群,参与贡献,打造下一代消息、事件、流融合处理平台。

20.jpeg

微信扫码添加小火箭进群

另外还可以加入钉钉群与 RocketMQ 爱好者一起广泛讨论:

21.png

钉钉扫码加群

关注「Apache RocketMQ」公众号,获取更多技术干货



推荐阅读
  • 修复一个 Bug 竟耗时两天?真的有那么复杂吗?
    修复一个 Bug 竟然耗费了两天时间?这背后究竟隐藏着怎样的复杂性?本文将深入探讨这个看似简单的 Bug 为何会如此棘手,从代码层面剖析问题根源,并分享解决过程中遇到的技术挑战和心得。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • Java队列机制深度解析与应用指南
    Java队列机制在并发编程中扮演着重要角色。本文深入解析了Java队列的各种实现类及其应用场景,包括`LinkedList`、`ArrayBlockingQueue`和`PriorityQueue`等,并探讨了它们在高并发环境下的性能表现和适用场景。通过详细分析这些队列的内部机制和使用技巧,帮助开发者更好地理解和应用Java队列,提升系统的设计和架构能力。 ... [详细]
  • 本文提供了 RabbitMQ 3.7 的快速上手指南,详细介绍了环境搭建、生产者和消费者的配置与使用。通过官方教程的指引,读者可以轻松完成初步测试和实践,快速掌握 RabbitMQ 的核心功能和基本操作。 ... [详细]
  • IIS 7及7.5版本中应用程序池的最佳配置策略与实践
    在IIS 7及7.5版本中,优化应用程序池的配置是提升Web站点性能的关键步骤。具体操作包括:首先定位到目标Web站点的应用程序池,然后通过“应用程序池”菜单找到对应的池,右键选择“高级设置”。在一般优化方案中,建议调整以下几个关键参数:1. **基本设置**: - **队列长度**:默认值为1000,可根据实际需求调整队列长度,以提高处理请求的能力。此外,还可以进一步优化其他参数,如处理器使用限制、回收策略等,以确保应用程序池的高效运行。这些优化措施有助于提升系统的稳定性和响应速度。 ... [详细]
  • ZeroMQ在云计算环境下的高效消息传递库第四章学习心得
    本章节深入探讨了ZeroMQ在云计算环境中的高效消息传递机制,涵盖客户端请求-响应模式、最近最少使用(LRU)队列、心跳检测、面向服务的队列、基于磁盘的离线队列以及主从备份服务等关键技术。此外,还介绍了无中间件的请求-响应架构,强调了这些技术在提升系统性能和可靠性方面的应用价值。个人理解方面,ZeroMQ通过这些机制有效解决了分布式系统中常见的通信延迟和数据一致性问题。 ... [详细]
  • 近期,为编制《2018中国人工智能应用与生态研究报告》,中国软件网对国内人工智能产业的应用现状、平台建设和生态系统进行了深入调研。本报告详细分析了当前人工智能企业的发展阶段,并对其未来前景进行了全面评估。研究发现,人工智能技术在多个领域取得了显著进展,但同时也面临诸多挑战,如数据安全、技术成熟度和人才短缺等。报告还探讨了政策支持、行业合作和技术突破对推动人工智能产业发展的关键作用。 ... [详细]
  • 前言: 网上搭建k8s的文章很多,但很多都无法按其说明在阿里云ecs服务器成功搭建,所以我就花了些时间基于自己成功搭建k8s的步骤写了个操作手册,希望对想搭建k8s环境的盆友有所帮 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • 为何Serverless将成为未来十年的主导技术领域?
    为何Serverless将成为未来十年的主导技术领域? ... [详细]
  • Android开发常见问题汇总(含Gradle解决方案)第二篇
    本文继续深入探讨Android开发中常见的问题及其解决方案,特别聚焦于Gradle相关的挑战。通过详细分析和实例演示,帮助开发者高效解决构建过程中的各种难题,提升开发效率和项目稳定性。 ... [详细]
  • 基于STM32的智能太阳能路灯设计与华为云IOT集成方案
    基于STM32的智能太阳能路灯设计与华为云IOT集成方案 ... [详细]
  • 自1995年问世以来,Java已历经14年的演变,在快速发展的信息技术领域中展现出持续的活力与创新。如今,Java不仅是一种编程语言,更发展成为一个多功能平台、活跃的开发者社区及成熟的技术生态系统。 ... [详细]
  • 如果你对 IntelliJ IDEA 的界面不太熟悉,可能会对如何在 Android Studio 中执行一些常见任务感到困惑。本文提供了多种开发技巧和实用窍门,帮助开发者更好地利用 Android Studio 的强大功能,包括界面导航、代码调试和项目管理等方面,使开发过程更加高效顺畅。 ... [详细]
  • 如何使用 `com.amazonaws.services.sqs.model.DeleteMessageRequest` 的 `getQueueUrl()` 方法及其代码示例解析 ... [详细]
author-avatar
手机用户2502881923
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有