RocketMQ的消息是存储到Topic的queue里面的,queue本身是FIFO(First Int First Out)先进先出队列。所以单个queue是可以保证有序性的。
但问题是1个topic有N个queue,作者这么设计的好处也很明显,天然支持集群和负载均衡的特性,将海量数据均匀分配到各个queue上,你发了10条消息到同一个topic上,这10条消息会自动分散在topic下的所有queue中,所以消费的时候不一定是先消费哪个queue,后消费哪个queue,这就导致了无序消费。
如何保证:
两种方案:
方案一:都发到一个queue上即可,rocketMq提供了MessageQueueSelector。RocketMQTemplate则对其封装提供了发送带Orderly的方法,将hashKey的值直接固定即可
方案二:通过hashKey的值将有顺序的消息发到同一个队列上去,比方说在财务服务中我是通过组织id的hashcode对线程池数8取余作为hashKey,使得消息落到固定队列上从而保证同一个账户消费的顺序性,同时消息按comId分组后,遍历comId计算hashCode对8取余放入map,再遍历该map从线程池列表取对应线程池然后提交任务,增了程序的并发能力。