Apache RocketMQ 5.0 消息进阶:如何支撑复杂的业务消息场景?

news2025/1/21 8:56:20

作者:隆基

一致性

首先来看 RocketMQ 的第一个特性-事务消息,事务消息是 RocketMQ 与一致性相关的特性,也是 RocketMQ 有别于其他消息队列的最具区分度的特性。

图片

以大规模电商系统为例,付款成功后会在交易系统中订单数据库将订单状态更新为已付款。然后交易系统再发送一条消息给 RocketMQ,RocketMQ 将订单已付款的事件通知给所有下游应用,保障后续的履约环节。

但上述流程存在一个问题,交易系统写数据库与发消息互相分开,它不是一个事务,会出现多种异常情况,比如数据库写成功但消息发失败,这个订单的状态下游应用接收不到,对于电商业务来说,可能造成大量用户付款但卖家不发货的情况;而如果先发消息成功再写数据库失败,会造成下游应用认为订单已付款,推进卖家发货,但是实际用户未付款成功。这些异常都会对电商业务造成大量脏数据,产生灾难性业务后果。

而 RocketMQ 事务消息的能力可以保障生产者的本地事务(如写数据库)、发消息事务的一致性,最后通过 Broker at least once 的消费语义,保证消费者的本地事务也能执行成功,最终实现生产者、消费者对同一业务的事务状态达到最终一致。

一致性:事务消息-原理

如下图所示,事务消息主要通过两阶段提交+事务补偿机制结合实现。

图片

首先生产者会发送 half 消息,也就是 prepare 消息,broker 会把 half 存到队列中。接下来生产者执行本地事务,一般是写数据库,本地事务完成后,会往 RocketMQ 发送 commit 操作,RocketMQ 会把 commit 操作写入 OP 队列,并进行 compact,把已提交的消息写到 ConsumeQueue 对消费者可见。反过来如果是 rollback 操作,则会跳过对应的 half 消息。

面对异常的情况,比如生产者在发送 commit 或者 rollback 之前宕机了,RocketMQ broker 还会有补偿检查机制,定期回查 Producer 的事务状态,继续推进事务。

无论是 Prepare 消息、还是 Commit/Rollback 消息、或者是 compact 环节,在存储层面都是遵守 RocketMQ 以顺序读写为主的设计理念,达到最优吞吐量。

一致性:事务消息 demo

接下来来看一个事务消息的简单示例。使用事务消息需要实现一个事务状态的查询器,这也是和普通消息一个最大的区别。如果我们是一个交易系统,这个事务回查器的实现可能就是根据订单 ID 去查询数据库来确定这个订单的状态到底是否是提交,比如说创建成功、已付款、已退款等。主体的消息生产流程也有很多不同,需要开启分布式事务,进行两阶段提交,先发一个 prepare 的消息,然后再去执行本地事务。这里的本地事务一般就是执行数据库操作。然后如果本地事务执行成功的话,就整体 commit,把之前的 prepare 的消息提交掉。这样一来消费者就可以消费这条消息的。如果本地事务出现异常的话,那么就把整个事务 rollback 掉,之前的那条 prepare 的消息也会被取消掉,整个过程就回滚了。事务消息的用法变化主要体现在生产者代码,消费者使用方式和普通消息一致,demo 里面就不展示了。

图片

一致性:顺序消息场景+原理

RocketMQ 的第二个高级特性是顺序消息,也是特色能力之一。它解决了顺序一致性的问题,保障同一业务的消息,生产与消费的顺序保持一致。

阿里曾有一个场景是买卖家数据库复制,由于阿里订单数据库采用分库分表技术,面向买卖家不同的业务场景,会分别按照买家主键与卖家主键拆分为买卖家数据库。两个数据库的同步采用 Binlog 顺序分发的机制,通过使用顺序消息,将买家库的 Binlog 变更按照严格顺序在卖家库回放,以此达到订单数据库的一致性。如果没有顺序保障,则可能出现数据库级别的脏数据,会带来严重的业务错误。

顺序消息的实现原理如下图所示,充分利用 Log 天然顺序读写的特点高效实现。

图片

在 Broker 存储模型中,每个 Topic 都会有固定的 ConsumeQueue,可以理解为 Topic 的分区。生产者为发送消息加上业务 Key,在这个 case 里面可以用订单 ID,同一订单 ID 的消息会顺序发送到同一个 Topic 分区,每个分区在某个时刻只会被一个消费者锁定,消费者顺序读取同一个分区的消息串行消费,以此来达到顺序一致性。

一致性:顺序消息 demo

接下来来看顺序消息的一个简单 demo。对于顺序消息而言,生产者与消费者都有需要注意的地方。

图片

在生产阶段,首先要定义消息的 group。每条消息都可以选择业务 ID 作为消息 Group,业务 ID 尽量离散、随机。因为同一业务 ID 会分配到同一数据存储分片,生产与消费都在该数据分片上串行,如果业务 ID 有热点,会造成严重的数据倾斜与局部消息堆积。

比如在电商交易的场景,选择订单 ID、买家 ID 会比较好,比较离散。如果选择的是卖家 ID,则可能会出现热点,热点卖家的流量会远大于普通卖家。

消费阶段也与常规的消息收发有所区别,主要有两种模式,分别是全托管的 push consumer 模式和半托管主动获取消息的 simple consumer 模式。RocketMQ SDK 会保障同一分组的消息串行进入业务消费逻辑。需要注意,自身的业务消费代码也要串行进行,然后同步返回消费成功确认。不要将同一分组的消息放到另外的线程池消并发费,会破坏顺序语义。

复杂业务

复杂业务:SQL 过滤场景

RocketMQ 的第三个高级特性是 SQL 消费模式,也是复杂业务场景的刚需。

图片

如上图,阿里的电商业务围绕着交易展开,有数百个不同的业务在订阅交易消息。业务基本面向某个细分领域,都只需要交易 Topic 下的部分消息。按照传统的模式,一般是全量订阅交易 Topic,在消费者本地过滤即可,但这样会消耗大量计算、网络资源,特别是在双十一,该方案的成本是无法接受的。

复杂业务:SQL过滤原理

为了解决上述问题,RocketMQ 提供了 SQL 消费模式。在交易场景下,每笔订单消息都会带有不同维度的业务属性,包括卖家 ID、买家 ID、类目、省市、价格、订单状态等属性,而 SQL 过滤能让消费者通过 SQL 语句过滤消费目标消息。比如,某个消费者只想关注某个价格区间内的订单创建消息,创建订阅关系 Topic=Trade SQL:status=ordercreate and(Price between 50 and 100),Broker 会在服务端运行 SQL 计算,只返回有效数据给消费者。

为了提高性能,Broker 还引入了布隆过滤器模块。在消息写入分发时刻提前计算结果,写入位图过滤器,减少无效 IO。

总体而言,其本质为将过滤链路不断前置,从消费端本地过滤,到服务端写时过滤,达到最优性能。

图片

复杂业务:SQL 过滤 demo

接下来看一个 SQL 订阅的示例。目前 RocketMQ SQL 过滤支持属性非空判断、属性大小比较、属性区间过滤、集合判断与逻辑计算,能满足绝大部分的过滤需求。

图片

在消息生产阶段,除了设置 Topic、Tag 之外,还能添加多个自定义属性。比如在这案例里,设置了一个 region 的属性,表示该条消息从杭州 region 发出。消费时可根据自定义属性来进行 SQL 过滤订阅。第一个 case 是用了一个 filter expression,判断 region 这个字段不为空且等于杭州才消费。第二个 case 添加更多的条件,如果这是一笔订单消息,还可以同时判断 region 条件和价格区间来决定是否消费。第三个 case 是全接收模式,表达式直接为 True,这个订阅方式会接收某一个主题下面的全量消息,不进行任何过滤。

复杂业务:定时消息场景+原理

RocketMQ 的第四个高级特性是定时消息。

图片

生产者可以指定某条消息在发送后经过一定时间后才对消费者可见。有不少业务场景需要大规模的定时事件触发,比如典型的电商场景基本都有订单创建 30 分钟未付款自动关闭订单的逻辑,定时消息能为上述场景带来极大的便利性。

RocketMQ 的定时消息基于时间轮(TimerWheel)来实现。通过模拟表盘转动来达到对时间进行排序的目的。

TimerWheel 中的每一格代表最小的时间刻度,称为 Tick。RocketMQ 里,每一个 Tick 为一秒,同一时刻的消息会写入到同一格子里。由于每个时刻可能会同时触发多条消息,并且每条消息的写入时刻都不一样,因此 RocketMQ 也同时引入了 Timerlog 的数据结构,Timerlog 按照顺序 append 的方式写入数据,每个元素都包含消息的物理索引以及指向同一时刻的前一条消息,组成逻辑链表。TimeWheel 的每个格子都维护该时刻的消息链表的头尾指针。

TimerWheel 会有指针,代表当前时刻,绕着 TimerWheel 循环转动,指针所指之处代表该 Tick 到期,所有内容一起弹出,写到 ConsumeQueue,对消费者可见。

目前 RocketMQ 的定时消息性能已经远超 RabbitMQ 与 ActiveMQ。

图片

全局高可用

接下来再讲一下 RocketMQ 的全局高可用技术解决方案。RocketMQ 的高可用架构主要指 RocketMQ 集群内的数据多副本与服务高可用。而本文的高可用是全局的、业界常说的同城容灾、两地三中心、异地多活等架构。

图片

目前,蚂蚁支付与阿里交易均采用异地多活的架构,异地多活相对于冷备、同城容灾、两地三中心模式具备更多优点,可以应对城市级别的灾难,如地震、断电等事件。除此之外,针对一些因为人为操作引起的问题,比如某个基础系统变更引入新的 bug,导致整个机房级别的不可用,异地多活架构可以直接将流量切到可用机房,优先保障业务连续性,再定位具体的问题。

另一方面,异地多活还能实现机房级别的扩容,单一机房的计算存储资源有限,而异地多活架构可以将业务流量按照比例分散在全国各地机房。同时,多活架构实现了所有机房都提供业务服务,而不是冷备状态,资源利用率大幅度提升。得益于多活状态,面对极端场景的切流,可用性更有保障,信心更足。

在异地多活的架构中,RocketMQ 承担的是基础架构的多活能力。多活的架构分为几个模块:

  • 接入层: 通过统一接入层按照业务 ID 将用户请求分散到多个机房,业务 ID 一般可采用用户 ID。
  • 应用层: 应用层一般无状态,当请求进入某个机房后,需要尽量保障该请求的整个链路都在单元内封闭,包括 RPC、数据库访问、消息读写,可降低访问延迟,保障系统性能不会因为多活架构衰退。
  • 数据层: 包括数据库、消息队列等有状态系统。RocketMQ 通过 connector 组件实现按 topic 粒度实时同步消息的数据,按照 Consumer 与 Topic 的组合粒度实时同步消费状态。
  • 全局的管控层: 需要维护全局的单元化规则,分配哪些流量走到哪些机房;还需要管理多活元数据配置,哪些应用需要多活、哪些 Topic 需要多活;另外,在切流时刻需要协调所有系统的切流过程,控制切流顺序。

总结

本篇文章介绍了很多 RocketMQ 的高阶特性。首先是一致性的特性,这里面就包括了顺序的一致性、分布式业务的一致性;RocketMQ 在应对大规模复杂业务的特性有 2 个,一个是 SQL 过滤订阅,可以应对那种单一超大业务大量消费者过滤需求;还有一个是定时消息,这也是很多互联网交易业务常见的场景。最后,介绍了 RMQ 在高阶的容灾能力方面的建设,提供了一个异地多活的解决方案。


【活动】带你玩转 RocketMQ,角逐「RocketMQ 首席评测官」

为了更好地长期得到开发者实际使用中的反馈和建议,联合阿里云开发者社区推出了“寻找 RocketMQ 首席评测官”活动,寻找在消息领域有技术实践经验、愿意深度评测产品并提出宝贵建议的开发者。期待您的加入,帮助 Apache RocketMQ 以及阿里云消息产品持续提升竞争力。
**活动入口
**

点击此处立即参与活动:

https://developer.aliyun.com/topic/rocketmq?utm_content=g_1000377381&spm=1000.2115.3001.5954

可以直接进行产品评测:

https://developer.aliyun.com/mission/review/rocketmqtest?spm=a2c6h.28281744.J_2889796290.5.c66c5bacLDNt46

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/943219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三---开关稳压器

通过控制系统反馈,当电压上升时通过反馈降低,当电压下降时通过反馈升高;形成一个控制环路;控制电路:PWM(脉宽调制),PFM(频率控制方式),移相控制方…

2023开学季有哪些电容笔值得买?平价电容笔推荐

在日常生活中,这支电容笔的使用范围很广,不管是和电脑、IPAD、手机一起使用,都可以说是一种很好的办公工具。首先要弄清楚自己的需求,再根据自己的需求来挑选合适的商品。苹果的Pencil有一种独特的重力压感,让人在上面…

【MTK平台】根据kernel log分析wifi scan的时候流程

一 概要: 本文主要讲解根据kernel log分析下 当前路径下(vendor/mediatek/kernel_modules/connectivity/wlan/core/gen4m/)wifi scan的时候代码流程 二. Log分析: 先看Log: 2.1)在Framework层WifiManager.java 方法中,做了一个标记,可以精准的确认时间 这段log可以…

基于Qt5开发图形界面——WiringPi调用Linux单板电脑IO

Qt5——WiringPi Qt5WiringPi示例教程 Qt5 Qt是一种跨平台的应用程序开发框架。它被广泛应用于图形用户界面(GUI)开发,可以用于构建桌面应用程序、移动应用程序和嵌入式应用程序。Qt提供了丰富的功能和工具,使开发人员可以快速、高…

企业内部搭建wiki的意义大吗?到底有何价值体现?

内部Wiki也叫做企业Wiki,是员工可以存储、共享和协作创作的地方,将企业内部员工知识共享集中到一个地方,并且相关内容与其他团队成员协作完成,它可以包含企业内部的各种知识,从操作指南到培训手册,再到客户…

ipad有必要用手写笔吗?开学季实惠的电容笔推荐

iPad平板的机型经过了一次又一次的升级,增加了更多的功能,如今已有了与笔记本电脑匹敌的能力。而到了如今,科技的发展,iPad也从一个娱乐工具,变成了一个集学习、画画、办公于一体的强大工具。为了提高生产效率&#xf…

Linux内核学习(十二)—— 页高速缓存和页回写(基于Linux 2.6内核)

目录 一、缓存手段 二、Linux 页高速缓存 三、flusher 线程 Linux 内核实现了一个被叫做页高速缓存(page cache)的磁盘缓存,它主要用来减少对磁盘的 I/O 操作。它是通过把磁盘中的数据缓存到内存中,把对磁盘的访问变为对物理内…

比较器DATESHEET参数

失调电压的理解 Input Offset Voltage 理想情况下,如果运算放大器的两个输入电压完全相同,则输出应为0V。但运放内部两输入支路无法做到完全平衡,导致输出永远不会是0,具体见图1所示。此时保持放大器负输入端不变,而在…

火绒能一键修复所有dll缺失吗?教你快速修复dll文件

关于dll文件的缺少,其实大家应该都是不陌生的吧,毕竟只要是经常使用电脑的人,那么它就一定碰到过各种各样的dll文件缺失,因为很多程序都是需要dll文件来支撑的,如果dll文件丢失了,那么一些程序就会启动不了…

新版白话空间统计(27):从离散点到密度图

点的密度是点分析中一个很重要的方向,有大量的点数据的空间表达,基本上都是通过密度图来进行体现的,比如百度热力图: 又或者是交通车流量热力图: 空间点密度分析,把海量离散的点,变成高度抽象的…

Tableau可视化进阶实践-1

各类地图 符号地图特点 填充地图特点 多维地图特点 混合地图特点 符号地图 特点 符号化:符号地图以符号的形式表示信息,使用不同的符号来代表不同的地理要素或特定的地理信息。这种符号化的方式可以简化地理信息的表达,使人们更容易理解和识…

基于ssm+vue斗车车辆交易系统源码和论文

基于ssmvue斗车交易系统源码和论文082 开发工具:idea 数据库mysql5.7 数据库链接工具:navcat,小海豚等 技术:ssm 摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次…

一个程序员眼中的API调用(淘宝/天猫/1688/拼多多API)

在程序员眼中,API调用是一种重要的编程概念,它允许开发人员通过预先定义好的接口和规范,调用其他应用程序或服务的功能。API调用是现代软件开发中不可或缺的一部分,它使得开发人员能够快速构建出复杂的应用程序,同时避…

电子电路原理题目整理(1)

电子电路原理题目整理(1) 最近在学习《电子电路原理》,记录一下书后面试题目,答案为个人总结,欢迎讨论。 1.电压源和电流源的区别? 电压源在不同的负载电阻下可提供恒定的负载电压,而电流源对于…

升讯威在线客服系统的并发高性能数据处理技术:具体化视图

我在业余时间开发维护了一款免费开源的升讯威在线客服系统,也收获了许多用户。对我来说,只要能获得用户的认可,就是我最大的动力。 最近客服系统成功经受住了客户现场组织的压力测试,获得了客户的认可。 客户组织多名客服上线后&a…

MySQL之事务与引擎

目录 一、事物 1、事务的概念 2、事务的ACID特点 3、事务之间的相互影响 4、Mysql及事务隔离级别(四种) 5、演示 1、查询会话事务隔离级别 2、查询会话事务隔离级别 3、设置全局事务隔离级别 4、设置会话事务隔离级别 6、事务控制语句 7、演示 1、测试提交事务 2、测试事…

Linux项目自动化构建工具-Makefile

Makefile Makefile介绍Makefile的使用依赖关系/依赖方法伪目标文件make 工作方式make [命令] 使用方式 Makefile介绍 Makefile是一个自动化编译工具,写好后,我们只需一个make命令,程序即可完成编译命令,并且可以根据项目需要&…

深圳前海公司的优惠政策

1.金融服务业政策优势 1.1支持前海构建跨境人民币业务创新试验区; 1.2探索试点跨境贷款; 1.3支持前海企业赴港发行人民币债券; 1.4支持设立前海股权投资母基金; 1.5支持外资股权投资基金在前海创新发展; 1.6支持…

android studio git没有显示Local Changes界面

设置android studio git没有显示Local Changes界面 Setting -> Version Control-> commit -> 把use non-modal commit interface 的勾勾去掉,如下图所示 然后点击apply,回到git界面就看到了,亲测有效

Qt应用开发(基础篇)——颜色选择器 QColorDialog

一、前言 QColorDialog类继承于QDialog,是一个设计用来选择颜色的对话框部件。 对话框窗口 QDialog QColorDialog颜色选择器一般用来让用户选择颜色,比如画图工具中选择画笔的颜色、刷子的颜色等。你可以使用静态函数QColorDialog::getColor()直接显示对…