解决rabbitmq消息队列的顺序及重复消费问题

五一期间去韩国游玩,顺便去了朋友公司扯淡去了。 所谓的扯淡,就是过去听技术分享,有python, golang, devops,docker一些话题。总的来说,技术方面跟国内还是有一些差距的。 

正题开始,因为业务的各方面的强需求,我们使用了rabbitmq作为消息队列,利用rabbitmq的ack机制来确认消息的可靠性。 但是rabbitmq本身是没有绝对的消息顺序机制的,单个queue在多消费者下不能保证其先后顺序。  另外ack的机制会触发消息重复消费的,需要我们在设计上避免该问题。


该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新.  http://xiaorui.cc/?p=4493

关于消息的重复执行

首先我们可以确认的是,触发消息重复执行的条件会是很苛刻的! 也就说 在大多数场景下不会触发该条件!!! 一般出在任务超时,或者没有及时返回状态,引起任务重新入队列,重新消费!  在rabbtimq里连接的断开也会触发消息重新入队列。  

消费任务类型最好要支持幂等性,这样的好处是 任务执行多少次都没关系,顶多消耗一些性能! 如果不支持幂等,比如发送信息? 那么需要构建一个map来记录任务的执行情况! 不仅仅是成功和失败,还要有心跳!!!  这个map在消费端实现就可以了!!!    这里会出现一个问题,有两个消费者 c1, c2 ,一个任务有可能被c1消费,如果再来一次,被c2执行? 那么如何得知任务的情况? 任务派发!  任务做成hash,固定消费者!
坚决不要想方设法在mq扩展这个future。

一句话,要不保证消息幂等性,要不就用map记录任务状态.

关于消息的绝对顺序执行

我们遇到的大多数场景都不需要消息的有序的,如果对于消息顺序敏感,那么我们这里给出的方法是 消息体通过hash分派到队列里,每个队列对应一个消费者,多分拆队列。
为什么要这么设计?  同一组的任务会被分配到同一个队列里,每个队列只能有一个worker来消费,这样避免了同一个队列多个消费者消费时,乱序的可能! t1, t2 两个任务, t1 虽然被c1先pop了,但是有可能c2先把 t2 任务给完成了。

一句话,主动去分配队列,单个消费者。

基于Rabbitmq的多任务处理框架

这里提一下,我们用rabbitmq实现了一个颇为复杂的架构,节省了太多的mq连接及消耗。通过python pika gevent实现的,因py有gil,所以使用多进程来跑多核,进程之间不使用共享变量,而是用队列来传递ack信号。  

这里实现的场景是用pika消费rabbitmq,然后把获取到的任务提丢到队列,另一个进程去消费该任务,然后触发ack。 

END.


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc