顺序消息常用于金融证券、电商业务等对消息指令顺序有严格要求的场景。相对于顺序消息1.0版本,2.0版本具有更高的并发性、可用性和抗热点能力。本文介绍消息队列RocketMQ版顺序消息2.0的基本概念、实现原理、功能优势以及使用过程中的注意事项。
什么是顺序消息
顺序消息是消息队列RocketMQ版提供的一种对消息发送和消费顺序有严格要求的消息。对于一个指定的Topic,消息严格按照先进先出(FIFO)的原则进行消息发布和消费,即先发布的消息先消费,后发布的消息后消费。
分区顺序消息
对于指定的一个Topic,所有消息根据Sharding Key进行区块分区,同一个分区内的消息按照严格的先进先出(FIFO)原则进行发布和消费。同一分区内的消息保证顺序,不同分区之间的消息顺序不做要求。
- 基本概念
- Sharding Key:顺序消息中用来区分Topic中不同分区的关键字段,和普通消息的Key是完全不同的概念。消息队列RocketMQ版会将设置了相同Sharding Key的消息路由到同一个分区下,同一个分区内的消息将按照消息发布顺序进行消费。
- 分区:即Topic Partition,每个Topic包含一个或多个分区,Topic中的消息会分布在这些不同的分区中。本文中的逻辑分区指的就是Topic的分区,更多信息,请参见名词解释。
- 物理分区:区别于逻辑分区,消息实际存储的单元,每个物理分区都会分配到某一台机器指定节点上。
- 适用场景
适用于性能要求高,以Sharding Key作为分区字段,在同一个区块中严格地按照先进先出(FIFO)原则进行消息发布和消费的场景。
- 示例
- 用户注册需要发送验证码,以用户ID作为Sharding Key,那么同一个用户发送的消息都会按照发布的先后顺序来消费。
- 电商的订单创建,以订单ID作为Sharding Key,那么同一个订单相关的创建订单消息、订单支付消息、订单退款消息、订单物流消息都会按照发布的先后顺序来消费。
阿里巴巴集团内部电商系统均使用分区顺序消息,既保证业务的顺序,同时又能保证业务的高性能。
全局顺序消息
对于指定的一个Topic,所有消息按照严格的先入先出(FIFO)的顺序来发布和消费。
- 适用场景
适用于性能要求不高,所有的消息严格按照FIFO原则来发布和消费的场景。
- 示例
在证券处理中,以人民币兑换美元为Topic,在价格相同的情况下,先出价者优先处理,则可以按照FIFO的方式发布和消费全局顺序消息。
如何保证消息的顺序
全局顺序消息和分区顺序消息原理一样,下文以分区顺序消息为例介绍在消息队列RocketMQ版中如何保证消息的顺序。
- 消息发送
如上图所示,A1、B1、A2、A3、B2、B3是订单A和订单B的消息产生的顺序,业务上要求同一订单的消息保持顺序,例如订单A的消息发送和消费都按照A1、A2、A3的顺序。如果是普通消息,订单A的消息可能会被轮询发送到不同的队列中,不同队列的消息将无法保持顺序,而顺序消息发送时消息队列RocketMQ版支持将Sharding Key相同(例如同一订单号)的消息序路由到一个分区中。
- 消息存储
顺序消息2.0中,Topic中的每个逻辑分区可以对应多个物理分区,当消息按照顺序发送到Topic中的逻辑分区时,每个分区的消息将按照负载均匀的存储到对应的多个物理分区中,在物理分区中消息的存储可以不用保持顺序,但消息队列RocketMQ版中会记录消息在逻辑分区和物理分区中的映射关系及存储位置。
- 消息消费
即使同一逻辑分区的消息被存储在不同的物理分区中且没有保持消息的顺序,但是基于顺序消息2.0的保序协议,消息队列RocketMQ版服务端在投递消息时,最终还是会按照消息在逻辑队列中存储的顺序投递给Consumer,Consumer消费消息时,同一Sharding Key的消息使用单线程消费,保证消息消费顺序和存储顺序一致,最终实现消费顺序和发布顺序的一致。
顺序消息2.0功能优势
- 无热点
一个逻辑分区可以对应多个物理分区,消除了因为物理分区性能瓶颈导致的逻辑分区热点问题。即使是全局顺序消息,也不会出现单个逻辑分区的热点问题。
- 高并发无限扩展
在保持顺序的前提下,每个逻辑分区对应的物理分区可以无限水平扩展,极大提高消息处理的并发性,并且业务侧无感知,也不需额外的业务改造成本。
- 故障秒级恢复
单个物理分区故障,其他物理分区可继续处理消息,达到秒级切换,业务基本无感知。
注意事项
使用顺序消息2.0时,请注意以下几点:
- 如需使用顺序消息2.0特性,请确保您的消息队列RocketMQ版实例是企业铂金版。
- 仅TCP Java ons-client v1.8.7.1.Final及以上版本的SDK支持顺序消息2.0。
- 同一个Group ID只对应一种类型的Topic,即不同时用于顺序消息和无序消息的收发。
- 对于全局顺序消息,建议消息不要有阻塞。同时运行多个实例,是为了防止工作实例意外退出而导致业务中断。当工作实例退出时,其他实例可以立即接手工作,不会导致业务中断,实际工作的只会有一个实例。
-
消息队列RocketMQ版服务端判定消息产生的顺序性是参照单一生产者、单一线程并发下消息发送的时序。如果发送方有多个生产者或者有多个线程并发发送消息,则此时只能以到达消息队列RocketMQ版服务端的时序作为消息顺序的依据,和业务侧的发送顺序未必一致。
TCP SDK示例代码
TCP协议下的示例代码,请参见Java SDK收发顺序消息。
存量Topic升级说明
如果您使用的是顺序消息1.0,且需升级至顺序消息2.0,请提交工单交由产品方做迁移支持。
顺序消息常见问题
- 同一条消息是否可以既是顺序消息,又是定时消息和事务消息?
不可以。顺序消息、定时消息、事务消息是不同的消息类型,三者是互斥关系,不能叠加在一起使用。
- 顺序消息支持哪些地域?
支持消息队列RocketMQ版所有公共云地域和金融云地域。
- 为什么全局顺序消息性能一般?
全局顺序消息是严格按照FIFO的消息阻塞原则,即上一条消息没有被成功消费,那么下一条消息会一直被存储到Topic队列中。如果想提高全局顺序消息的TPS,可以升级实例配置,同时消息客户端应用尽量减少处理本地业务逻辑的耗时。
- 顺序消息支持哪种消息发送方式?
顺序消息只支持可靠同步发送方式,不支持异步发送方式,否则将无法严格保证顺序。
- 顺序消息是否支持集群消费和广播消费?
顺序消息暂时仅支持集群消费模式,不支持广播消费模式。