顺序消息
顺序消息是消息队列 RocketMQ 提供的一种对消息发送和消费顺序有严格要求的消息。对于一个指定的 Topic,消息严格按照先进先出(FIFO)的原则进行消息发布和消费,即先发布的消息先消费,后发布的消息后消费。
顺序消息分为 分区顺序消息
和 全局顺序消息
分区顺序消息
分区顺序 对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区。 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。 Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。 适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。
- Sharding Key:顺序消息中用来区分 Topic 中不同分区的关键字段,和普通消息的 Key 是完全不同的概念。消息队列 RocketMQ 会将设置了相同 Sharding Key 的消息路由到同一个分区下,同一个分区内的消息将按照消息发布顺序进行消费。
- 分区:即 Topic Partition,每个 Topic 包含一个或多个分区,Topic 中的消息会分布在这些不同的分区中。本文中的逻辑分区指的就是 Topic 的分区。
- 物理分区:区别于逻辑分区,消息实际存储的单元,每个物理分区都会分配到某一台机器指定节点上。
一般场景下,消息的发送顺序和消息生产的绝对时间顺序保持一致,生产者需要自己保证消息发送的顺序和生产顺序一致,建议使用单线程发送,若使用多线程发送消息,可能会造成消息发送顺序乱序。
Topic 中的每个逻辑分区可以对应多个物理分区,当消息按照顺序发送到 Topic 中的逻辑分区时,每个分区的消息将按照负载均匀的存储到对应的多个物理分区中,在物理分区中消息的存储可以不用保持顺序,但消息队列 RocketMQ 会记录消息在逻辑分区和物理分区中的映射关系及存储位置。
即使同一逻辑分区的消息被存储在不同的物理分区中且没有保持消息的顺序,消息队列 RocketMQ 服务端在投递消息时,最终还是会按照消息在逻辑队列中存储的顺序投递给 Consumer,Consumer 消费消息时,同一 Sharding Key 的消息使用单并发消费,保证消息消费顺序和存储顺序一致,最终实现消费顺序和发布顺序的一致
适用场景
适用于性能要求高,以 Sharding Key 作为分区字段,在同一个区块中严格地按照先进先出(FIFO)原则进行消息发布和消费的场景。
业务例子
- 用户注册需要发送验证码,以用户 ID 作为 Sharding Key,那么同一个用户发送的消息都会按照发布的先后顺序来消费。
- 电商的订单创建,以订单 ID 作为 Sharding Key,那么同一个订单相关的创建订单消息、订单支付消息、订单退款消息、订单物流消息都会按照发布的先后顺序来消费。
示例
代码依然使用 SpringCloud 整合 RocketMq 的方式
不同于之前文章中使用默认的 input output ,本例中我们使用自定义的方式来实现:
首先声明 Source 接口,注意这个接口不用实现,框架会有默认实现
public interface MySource {
@Output("output-order")
MessageChannel output4Order();
}
在消息发送时引入
@Autowired
private MySource mySource;
发送消息,消息内容为 order 实体&#