vivo 鲁班平台 RocketMQ 消息灰度方案

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
云原生网关 MSE Higress,422元/月
函数计算FC,每月15万CU 3个月
简介: 实践是检验真理的唯一标准,我们进行了详细的灰度功能校验,分别是灰度版本订阅的topic&tag不变、灰度版本订阅的topic增加、灰度版本订阅的topic减少、灰度版本订阅的tage变化以及灰度版本订阅的topic&tag混合变化。

1.jpeg

本文作者:区二立 - vivo 技术架构总监


方案背景


2.png


RocketMQ使用广泛,技术场景下,可以用于异步解耦,比如不同系统间调用业务链上做分段式处理或使用不同语言的两个系统间的解耦;可以用于数据同步,比如基础数据通过 MQ 广播到各个业务领域,实现业务领域的提效;高并发订单或 IM 的推送服务中,可以使用MQ做削峰填谷;此外,在分布式事务中,也可以通过 MQ 做最终一致性的事务方案。


RocketMQ在业务场景下可覆盖很多系统,包括营销系统、生产制造上的各种管控系统、公共平台上人资、移动办公等流程类系统、类似于钉钉的自建IM 工具以及大数据等。


3.png


随着以微服务化为基础的数字化建设转型,完成一项业务必须串联不同团队和不同应用。而不同应用的开发和发布周期相对独立,需要对接的版本不一,因此需要灰度方案。


对于HTTP的灰度,很多时候通用的网关即可提供较好的支持,甚至简单地用 Nginx 实现也可以达到效果。微服务层,以Dubbo为例,有各种分组比如有扩展的 SPI 补充实现,可以轻松解决灰度方面的困扰。而 MQ 的灰度却没有标准支持,很多系统直接放弃了MQ灰度,因此也不得不接受一定时间段内的错误重试。


MQ技术特点

4.png


Broker是消息服务的核心,提供了消息服务最重要的计算与存储功能。消息发送时会对应一个 Topic,Topic为逻辑上的概念,内部执行往往是以 Queue 为单位。以普通消息类型的 Topic为例,Topic一般有多个 Queue,如图中的TOPIC_V_PLACE_ORDER 共有四个Queue,分别在两个 broker 里, broker a 与 broker b 里各有两个Queue。任何一条消息都必定属于四个Queue中的某一条。


每条消息内可指定 tag 标志,用于在逻辑上进一步切分 topic,如上图中的tagA、tagB。切分维度有多种,可以是IoT,也可以是增值服务类的产品order等。不同tab 表示不同分类,但它们共享一个 topic。


Queue可以理解为物理上的区分,broker的commitLog用于存放消息。commitLog不区分 Topic和Queue,不同的 Topic消息内容会按实际接收的Queue存储到其对应的broker commitLog上,该消息只会在集群中的某个 broker commitlog 中存在。


Broker commitLog是公用的,到达某一个 broker的消息都会存在同一个 commitLog上,即一个commitLog会同时保存不同topic的内容。


CommitLog达到一定大小时(一般为1G),会新建新的commitLog用于存储和接收新消息。commitLog在物理上存储具体消息,因此必然需要文件记录Queue与 commitLog存储消息之间的位置映射。minOffset(最小位移)和maxOffset(最大位移)也是存储位置中的重要概念。


ConsumeGroupID与 groupID 强关联, groupID 消费时会在 broker上记录 topic Queue的消费位移,即会根据Queue记录不同 groupID 的consumerOffset。


5.png


无论是生产者还是消费者,MQ都使用 groupID 表示交互的角色。在集群消费的情况下,使用同一个 groupID 的两个 client 会做Queue的消费订阅分配,一般会尽量采取平分的方式。而独立的消费组比如上图中GID_V_PAYMENT,会独占 topic中的 4 条Queue。消费组之间相互独立、互不干扰,有各自的消费位移点。


不同的 RocketMQ 实例都有独立的 clientID,作为唯一标识与 broker打交道。


6.png


提交消费位点时,只能提交该消费位点前都已完成消息位移的消息。如上图,3、4两条消息都已被消费线程处理完成,但2依然在处理中,因此实际触发的提交位点为1。消息2完成处理后,会触发消息4的提交。


7.png


不同的 groupID 之间互相绝缘,但同一个 groupID 却会相互影响。订阅关系指标记了当前应用实例的 groupID 订阅了哪些 Topic(或topic的tag)。每一个应用实例或clientID 的订阅关系都会随着心跳包一起发送到 broker上,并在 broker上以 groupID 作为 key 来存储。


每个broker每次接收到不同实例的心跳包时,都会按 groupID 的维度校验、替换订阅关系,即同一个 groupID 的订阅关系会被替换。同一个 groupID 在不同应用实例、不同 clientID ,只要订阅的 Topic和 tag 有任何不同,都会被最后到来的心跳包的订阅关系覆盖。


如果在不同的应用实例中使用同一个 groupID ,而实例因版本原因导致订阅 Topic发生变化,则两组实例共存时会互相干扰,导致有些应用实例收不到想要的消息或收到错误的消息。而订阅关系是影响 MQ 灰度方案的核心因素。


8.png


上图clientID_001 和clientID_002同属一个消费组GID_C_INVENTORY, clientID_001订阅了TOPIC_A,clientID_002 订阅TOPIC_B,都使用同一消费组执行订阅,因此,按照分配策略,它们会被交叉分配。分配结果可能是clientID_001 和clientID_002平分TOPIC_A的两条Queue, 也可能会平分TOPIC_B的两条Queue,从而导致异常。这就是订阅方式不一致导致的分配错乱以及处理错乱。


常见灰度方案


9.png


常规的灰度方案一般都会选择不同的消费组,处理方式有影子 Topic、Tag过滤以及userProperty过滤。以上几种处理方式都会存在一些缺陷:比如如何保证所有灰度消息都被消费完毕?灰度需要切换时,如何保证灰度消息是被灰度环境消费?灰度订阅切换为正常订阅关系的时候,如何确认消费位点,如何衔接才能保证消息不丢失?此外,运维人员可能对RocketMQ或应用内部逻辑不清楚,实际的操控对运维人员而言也是巨大的挑战。


鲁班灰度方案


10.png


鲁班灰度方案的核心解决思路是将Queue隔离使用。


Queue是 Topic的实际执行单元,一个Topic有多个Queue。可以选择一部分Queue用于灰度,灰度Queue的数量、开始位置等可以在具体的实现里进行定义。如上图,首尾两个Queue专门用于灰度。因此,我们只需保障生产者与消费者的灰度与正常环境隔离使用即可,灰度环境的消息只从灰度的Queue里取,正常环境的消息从正常环境的Queue里拉取。


消费者中无论是灰度还是正常的应用集群,都使用同一个消费组。这会导致订阅关系非常容易不一致。针对于此,我们的解决方案是改造订阅关系。


11.png


Broker的订阅关系维护在 ConsumerGroupInfo 里,其中 subscriptionTable 负责维护 groupID 发送来的订阅心跳包。如果心跳包的订阅关系不一样,则会进行替换。我们新增了graySubscriptionTable 类,专门负责维护灰度的订阅关系。虽然是同一个groupID,但使用不同的类来分别维护灰度和非灰度的订阅关系。


12.png


生产者的发送策略如下:首先判断目标topic是否有灰度消费者,再判断当前消息是否属于灰度范围。如果是,则将灰度消失投递到灰度的Queue里;否则,投递到正常的Queue。

13.png


消费者按灰度拉取,正常集群只平分正常的Queue,灰度集群只平分灰度的Queue。如上图,ClientID_001与ClientID_002 只会分享正常的Queue,而ClientID_003与ClientID_004只分享灰度的Queue,他们共用一个消费组。


如果本消费组使用的topic没有灰度,但由于其他消费组影响涉及到灰度topic,则它也会平分拉取灰度的Queue。此外,如果topic没有涉及灰度集群,则灰度Queue会空置不使用,消费者不拉取,生产者不发送。将灰度集群切换为正常集群时,原先灰度的集群会保证将灰度Queue消费完成后才真正进行切换,业务上动态切换服务时,MQ 会自动根据实际消费进度进行细节上的管控,保障所有消息不丢弃。


14.png


除了业务灰度标识外,MQ也有自己的灰度标识需要处理,存储于Namesrv。生产者和消费者获取 Topic路由消息都由Namesrv提供,这也意味着生产者和消费者已经与Namesrv建立了连接。可以通过定期将灰度消息更新到Namesrv上,生产者也会定期将灰度信息拉到本地来打通整个链路。


Namesrv存储灰度关系时,需要一个有状态的数据库来进行保存。


15.png


如果灰度期间的延时消息在灰度结束后才投递,则会投递到正常Queue。延时消息临时存在数据库里,能够支持比较细粒度的延时定义。


全局顺序消息会由一条Queue变成两条Queue。我们修改了创建Queue的定义,灰度切换回正常环境时,会保证将灰度的消息处理完以后再处理正常的消息。


细节上的控制主要依赖灰度开关grayFlag和graySwitch两个标识位进行控制。


graySwitch标志使用灰度的逻辑以及平分所有 Topic里Queue的逻辑,能够兼容不参与灰度的应用,可以平分所有受其他灰度消费组影响的 Topic的所有Queue。


grayFlag 用于标记本实例是否为灰度实例,这会影响到订阅关系的保存。它会先查看graySwitch,再进行自己的判断。


灰度场景校验


实践是检验真理的唯一标准,我们进行了详细的灰度功能校验,分别是灰度版本订阅的topic&tag不变、灰度版本订阅的topic增加、灰度版本订阅的topic减少、灰度版本订阅的tage变化以及灰度版本订阅的topic&tag混合变化。


加入 Apache RocketMQ 社区


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

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


16.jpeg

微信扫码添加小火箭进群


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


17.png

钉钉扫码加群


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

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
25天前
|
消息中间件 运维 安全
C5GAME 游戏饰品交易平台借助 RocketMQ Serverless 保障千万级玩家流畅体验
游戏行业蓬勃发展,作为国内领先的 STEAM 游戏饰品交易的服务平台,看 C5GAME 如何利用 RocketMQ Serverless 技术,为千万级玩家提供流畅的游戏体验,同时降低成本并提升运维效率。
C5GAME 游戏饰品交易平台借助 RocketMQ Serverless 保障千万级玩家流畅体验
|
9天前
|
消息中间件 存储 运维
2024最全RabbitMQ集群方案汇总
本文梳理了RabbitMQ集群的几种方案,主要包括普通集群、镜像集群(高可用)、Quorum队列(仲裁队列)、Streams集群模式(高可用+负载均衡)和插件方式。重点介绍了每种方案的特点、优缺点及适用场景。搭建步骤包括安装Erlang和RabbitMQ、配置集群节点、修改hosts文件、配置Erlang Cookie、启动独立节点并创建集群,以及配置镜像队列以提高可用性和容错性。推荐使用Quorum队列与Streams模式,其中Quorum队列适合高可用集群,Streams模式则同时支持高可用和负载均衡。此外,还有Shovel和Federation插件可用于特定场景下的集群搭建。
96 2
|
9天前
|
消息中间件 RocketMQ
2024最全RocketMQ集群方案汇总
在研究RocketMQ集群方案时,发现网上存在诸多不一致之处,如组件包含NameServer、Broker、Proxy等。通过查阅官方文档,了解到v4.x和v5.x版本的差异。v4.x部署模式包括单主、多主、多主多从(异步复制、同步双写),而v5.x新增Local与Cluster模式,主要区别在于Broker和Proxy是否同进程部署。Local模式适合平滑升级,Cluster模式适合高可用需求。不同模式下,集群部署方案大致相同,涵盖单主、多主、多主多从等模式,以满足不同的高可用性和性能需求。
48 0
|
5月前
|
消息中间件 Java 测试技术
消息队列 MQ使用问题之数据流出规则是否支持平台的云RabbitMQ
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
2月前
|
消息中间件 存储 弹性计算
云消息队列 RabbitMQ 版方案评测
本文评估了阿里云《高弹性,低成本,云消息队列 RabbitMQ 实践》方案,从实践原理理解、部署体验、方案优势展现及业务场景匹配四个方面进行了深入分析。文中指出,该方案在解决消息积压、提高系统稳定性、支持弹性伸缩等方面表现优异,但也提出了在组件功能解释、实战案例提供等方面的改进建议,以期帮助用户更好地理解和应用该技术解决方案。
155 0
EMQ
|
5月前
|
物联网 Linux C语言
在 Windows 平台搭建 MQTT 服务
NanoMQ 有着强大的跨平台和可兼容能力,不仅可以用于以 Linux 为基础的各类平台,也为 Windows 平台提供了 MQTT 服务的新选择。
EMQ
124 7
在 Windows 平台搭建 MQTT 服务
|
4月前
|
消息中间件 固态存储 RocketMQ
RocketMQ消息堆积常见场景与处理方案
文章分析了在使用RocketMQ时消息堆积的常见场景,如消费者注册失败或消费速度慢于生产速度,并提供了相应的处理方案,包括提高消费并行度、批量消费、跳过非重要消息以及优化消费代码业务逻辑等。
|
6月前
|
消息中间件 SQL RocketMQ
消息队列 MQ产品使用合集之如何实现灰度
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
6月前
|
消息中间件 RocketMQ
消息队列 MQ产品使用合集之在开源延时消息插件方案中和原生延时消息方案中,同时设置参数是否会出现错乱
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
7月前
|
消息中间件 存储 Kafka
【深入浅出 RocketMQ原理及实战】「底层源码挖掘系列」透彻剖析贯穿一下RocketMQ和Kafka索引设计原理和方案
【深入浅出 RocketMQ原理及实战】「底层源码挖掘系列」透彻剖析贯穿一下RocketMQ和Kafka索引设计原理和方案
137 1

相关产品

  • 云消息队列 MQ