顺序消息可以保证消息的消费顺序和发送的顺序一致,即先发送的先消费,后发送的后消费,常用于金融证券、电商业务等对消息指令顺序有严格要求的场景。本文介绍消息队列RocketMQ版顺序消息1.0的概念、适用场景、实现原理以及使用过程中的注意事项。

什么是顺序消息

顺序消息是消息队列RocketMQ版提供的一种对消息发送和消费顺序有严格要求的消息。对于一个指定的Topic,消息严格按照先进先出(FIFO)的原则进行消息发布和消费,即先发布的消息先消费,后发布的消息后消费。

顺序消息分为分区顺序消息全局顺序消息

分区顺序消息

对于指定的一个Topic,所有消息根据Sharding Key进行区块分区,同一个分区内的消息按照严格的先进先出(FIFO)原则进行发布和消费。同一分区内的消息保证顺序,不同分区之间的消息顺序不做要求。

  • 基本概念
    • Sharding Key:顺序消息中用来区分Topic中不同分区的关键字段,消息队列RocketMQ版会将设置了相同Sharding Key的消息路由到同一个分区下,同一个分区内的消息将按照消息发布顺序进行消费。将和普通消息的Key是完全不同的概念。
    • 分区:即Topic Partition,每个Topic包含一个或多个分区,Topic中的消息会分布在这些不同的分区中。本文中的逻辑分区指的就是Topic的分区,更多信息,请参见名词解释
    • 物理分区:区别于逻辑分区,消息实际存储的单元,每个物理分区都会分配到某一台机器指定节点上。
  • 适用场景

    适用于性能要求高,以Sharding Key作为分区字段,在同一个区块中严格地按照先进先出(FIFO)原则进行消息发布和消费的场景。

  • 示例
    • 用户注册需要发送发验证码,以用户ID作为Sharding Key,那么同一个用户发送的消息都会按照发布的先后顺序来消费。
    • 电商的订单创建,以订单ID作为Sharding Key,那么同一个订单相关的创建订单消息、订单支付消息、订单退款消息、订单物流消息都会按照发布的先后顺序来消费。

阿里巴巴集团内部电商系统均使用分区顺序消息,既保证业务的顺序,同时又能保证业务的高性能。

全局顺序消息

对于指定的一个Topic,所有消息按照严格的先入先出(FIFO)的顺序来发布和消费。

  • 适用场景

    适用于性能要求不高,所有的消息严格按照FIFO原则来发布和消费的场景。

  • 示例

    在证券处理中,以人民币兑换美元为Topic,在价格相同的情况下,先出价者优先处理,则可以按照FIFO的方式发布和消费全局顺序消息。

说明 全局顺序消息实际上是一种特殊的分区顺序消息,即Topic中只有一个分区,因此全局顺序和分区顺序的实现原理相同。因为分区顺序消息有多个分区,所以分区顺序消息比全局顺序消息的并发度和性能更高。

如何实现顺序消息

全局顺序消息和分区顺序消息原理一样,下文以分区顺序消息为例介绍在消息队列RocketMQ版中如何保证消息收发的顺序。顺序消息1.0
消息队列RocketMQ版中,消息的顺序需要由以下三个阶段保证:
  • 消息发送

    如上图所示,A1、B1、A2、A3、B2、B3是订单A和订单B的消息产生的顺序,业务上要求同一订单的消息保持顺序,例如订单A的消息发送和消费都按照A1、A2、A3的顺序。如果是普通消息,订单A的消息可能会被轮询发送到不同的队列中,不同队列的消息将无法保持顺序,而顺序消息发送时消息队列RocketMQ版支持将Sharding Key相同(例如同一订单号)的消息序路由到一个分区中。

    一般场景下,消息的发送顺序和消息生产的绝对时间顺序保持一致,例如消息生产的顺序为:订单创建、订单付款、付款成功,则发送时也需要按照这个顺序。生产者需要自己保证消息发送的顺序和生产顺序一致,建议使用单线程发送,若使用多线程发送消息,可能会造成消息发送顺序乱序。

  • 消息存储

    如上图所示,顺序消息1.0中,Topic中的每个分区(逻辑分区)对应一个物理分区,当消息按照顺序发送到Topic中的逻辑分区时,每个分区的消息将按照同样的顺序存储到对应的物理分区中。

  • 消息消费

    消息队列RocketMQ版按照存储的顺序将消息投递给Consumer,Consumer收到消息后也不对消息顺序做任何处理,按照接收到的顺序进行消费。

    Consumer消费消息时,同一Sharding Key的消息使用单并发消费,保证消息消费顺序和存储顺序一致,最终实现消费顺序和发布顺序的一致。

顺序消息1.0中,一个逻辑分区只能对应一个物理分区,且分区数一旦确定无法更改。如果业务出现增长,单物理节点的性能会出现瓶颈,如果强行扩容会影响消息路由策略和顺序,拆分业务也会造成额外的改造成本。因此顺序消息1.0适用于业务比较稳定,消息量波动比较小,后期不需要进行扩容的场景。

如果考虑业务增长可能需要扩容的情况,建议可以使用顺序消息2.0,支持水平无限扩容并对业务透明,避免了分区顺序的热点问题,且单个物理节点故障时支持秒级切换,业务侧无感知。更多信息,请参见顺序消息2.0

注意事项

使用顺序消息1.0时,请注意以下几点:

  • 同一个Group ID只对应一种类型的Topic,即不同时用于顺序消息和无序消息的收发。
  • 对于全局顺序消息,建议消息不要有阻塞。同时运行多个实例,是为了防止工作实例意外退出而导致业务中断。当工作实例退出时,其他实例可以立即接手工作,不会导致业务中断,实际工作的只会有一个实例。
  • 同一分区内的消息必须使用单线程发送和订阅,若使用多线程则无法保证消息的顺序。

顺序消息常见问题

  • 同一条消息是否可以既是顺序消息,又是定时消息和事务消息?

    不可以。顺序消息、定时消息、事务消息是不同的消息类型,三者是互斥关系,不能叠加在一起使用。

  • 顺序消息支持哪些地域?

    支持消息队列RocketMQ版所有公共云地域和金融云地域。

  • 为什么全局顺序消息性能一般?

    全局顺序消息是严格按照FIFO的消息阻塞原则,即上一条消息没有被成功消费,那么下一条消息会一直被存储到Topic队列中。如果想提高全局顺序消息的TPS,可以升级实例配置,同时消息客户端应用尽量减少处理本地业务逻辑的耗时。

  • 顺序消息支持哪种消息发送方式?

    顺序消息只支持可靠同步发送方式,不支持异步发送方式,否则将无法严格保证顺序。

  • 顺序消息是否支持集群消费和广播消费?

    顺序消息暂时仅支持集群消费模式,不支持广播消费模式。

TCP SDK示例代码

TCP协议下的示例代码请参见以下文档:

HTTP SDK示例代码

HTTP协议下的收发顺序示例代码请参见以下文档: