RocketMQ-为什么基于RocketMQ进行订单库数据同步时会消息乱序?

无天有壁纸 2024-05-04 23:01:37
让属于同一个订单的消息进入一个MessageQueue 所以要解决这个消息的乱序问题,最根本的方法其实非常简单,就是得想办法让一个订单的消息进入到一个MessageQueue里去。 举个例子,比如对一个订单,先后执行了insert、update两条SQL语句,那么我们现在就必须要想办法让这个订单的2个消息都直接进入到Topic下的MessageQueue里去。 那么我们这个时候应该怎么做呢?完全可以根据订单id来进行判断,我们可以往MQ里发送消息的时候,根据订单id来判断一下,如果订单id相同,你必须保证他进入同一个MessageQueue。 我们这里可以采用取模的方法,比如有一个订单id是1000,可能有两个消息,对于这两个消息,我们必须要用订单id=1000对MessageQueue的数量进行取模,比如MessageQueue一共有15个,那么此时订单id=1000取模就是5。 通过这个方法,就可以让一个订单的消息都按照顺序进入到一个MessageQueue中去。 真的这么简单吗?获取消息的时候也得有序 我们来思考一下,真的就像上面说的那么简单,只要保证一个订单的消息都进入一个MessageQueue中就搞定了吗? 显然不是。我们必须保证推送MQ的时候,也必须是有序的。 Consumer有序处理一个订单的消息 接着我们可以想一下,一个Consumer可以处理多个MessageQueue的消息,但是一个MessageQueue只能交给一个Consumer来进行处理,所以一个订单的消息只会给一个Consumer来进行处理。 这就完了吗?万一消息处理失败了可以走重试队列吗? 在Consumer处理消息的时候,可能因为底层存储挂了导致消息处理失败,之前有说过,可以返回RECONSUME_LATER状态,然后broker会过会儿自动给我们重试。 但是这个方案绝对不能用在有序消息中,因为如果你的Consumer获取到订单的一个消息,结果处理失败了,此时返回了RECONSUME_LATER,那么这条消息会进入重试队列,过一会儿才会交给你重试。 但是此时broker会把下一条消息交给消费者来处理,万一处理成功了,就又会出现乱序问题。 对于有序消息的方案中,如果你遇到消息处理失败的场景,就必须返回SUSPEND_CURRENT_QUEUE_A_MOMENT这个状态,意思是先等一会儿,一会儿再继续处理这批消息,而不能把这批消息放入重试队列中去,然后直接处理下一批消息。
0 阅读:1

无天有壁纸

简介:感谢大家的关注