引言
在某些业务场景中,MQ需要保证消息的顺序性,比如支付订单应该在创建订单之后进行
如果不使用保证顺序的手段,由于多队列、网络等因素可能会导致先处理支付订单的消息再处理创建订单的消息,这样就会导致处理失败
为了避免这样的情况发生,使用MQ时有必要保证消息的顺序性,在RocketMQ中通常使用顺序发送消息和顺序消费消息来保证消息的顺序性
生产者端保证消息有序
当队列全局只有一个时,消息全局有序,此时只需要确保为单个生产者发送(多个生产者同时发送无法预估消息到达的顺序)
或者先生产创建订单的消息再生产支付订单的消息(确保消息不丢)由于全局有序只能有一个队列,队列的压力过大,所以不经常使用
更通用的做法是使用队列有序:在发送消息时通过一定的路由算法将需要有序的消息分发到同一个队列中,使用相同的队列保证有序性
顺序消息分类
RocketMQ 提供了两种顺序消息,即全局顺序消息和分区顺序消息。
-
全局顺序消息:指某个 Topic 下的所有消息都要保证顺序。在这种情况下,Topic 内部只能有一个队列,生产者将消息顺序发送到这个唯一的队列中。因为队列本身是 FIFO(先进先出)的数据结构,所以进入队列的消息天然有序。不过,由于只有一个队列,会导致并发度很低,吞吐量也会受到限制,因此全局顺序消息的使用场景相对较少。
-
分区顺序消息:指在一个分区(队列)内的消息有序,不同分区之间的消息可以无序。这是更常见的使用方式,既保证了一定程度的顺序性,又能通过多个分区提高系统的并发能力和吞吐量。
实现分区顺序消息的发送
为了实现分区顺序消息的发送,生产者在发送消息时需要指定消息的路由规则,确保同一业务逻辑下的消息被发送到同一个队列中。例如,在电商系统中,一个订单的不同状态变更消息需要保证顺序,那么可以使用订单 ID 作为消息的路由键。
private SendResult sendSelectImpl(
Message msg,