共计 4594 个字符,预计需要花费 12 分钟才能阅读完成。
一致性
首先来看 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 在高阶的容灾能力方面的建设,提供了一个异地多活的解决方案。
作者:隆基
点击立刻收费试用云产品 开启云上实际之旅!
原文链接
本文为阿里云原创内容,未经容许不得转载。