深入浅出消息队列---5、RabbitMQ公平性保证-灵析社区

提笔写架构

RabbitMQ公平性保证

消息的可靠性传输可以保证秒杀业务的公平性。关于秒杀业务的公平性,我们还需要考虑一点:消息的顺序性(先进入队列的消息先进行处理)

RabbitMQ消息顺序性

顺序性:消息的顺序性是指消费者消费到的消息和发送者发布的消息的顺序是一致的。

举个例子,不考虑消息重复的情况,如果生产者发布的消息分别为msgl、msg2、msg3,那么消费者必然也是按照msgl、msg2、msg3的顺序进行消费的。

目前很多资料显示RabbitMQ的消息能够保障顺序性,这是不正确的,或者说这个观点有很大的局限性。在不使用任何RabbitMQ的高级特性,也没有消息丢失、网络故障之类异常的情况发生,并且只有一个消费者的情况下,也只有一个生产者的情况下可以保证消息的顺序性如果有多个生产者同时发送消息,无法确定消息到达Broker 的前后顺序,也就无法验证消息的顺序性,因为每一次消息的发送都是在各自的线程中进行的。

RabbitMQ消息顺序错乱演示

生产者发送消息:

 1、不使用生产者确认机制,单生产者单消费者可以保证消息的顺序性

 2、使用了生产者确认机制,那么就无法保证消息到达Broker的前后顺序,因为消息的发送是异步发送的,每一个线程的执行时间不同

 3、生产端使用事务机制,保证消息的顺序性

 消费端消费消息:

 1、单消费者可以保证消息的顺序性

 2、多消费者不能保证消息的顺序,因为每一个消息的消费都是在各自的线程中进行,每一个线程的执行时间不同

RabbitMQ消息顺序性保障

生产端启用事务机制,单生产者单消费者。如果我们不考虑消息到达MQ的顺序,只是考虑对已经到达到MQ中的消息顺序消费,那么需要保证消费者是单消费者即可。

RabbitMQ重复消费

重复消费原因

首先我们可以确认的是,触发消息重复执行的条件会是很苛刻的! 也就说 在大多数场景下不会触发该条

 件!!! 一般出在任务超时,或者没有及时返回状态,引起任务重新入队列,重新消费! 在rabbtimq里连接的断开也会触发消息重新入队列。 如下图所示:


 由于服务端没有收到消费端的ack应答,因此该条消息还会重新进行投递。

幂等性保障方案

重复消费不可怕,可怕的是你没考虑到重复消费之后,怎么保证幂等性。所谓幂等性,就是对接口的多次调用所产生的结果和调用一次是一致的。通俗点说,就一个数据,或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错。

怎么保证消息队列消费的幂等性?这一点需要结合的实际的业务来进行处理:

 1、比如我们消费的数据需要写数据库,你先根据主键查一下,如果这数据都有了,你就别插入了,执行以下update操作

 2、比如我们消费的数据需要写Redis,那没问题了,反正每次都是 set,天然幂等性。

 3、比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据这个id 去比如 Redis 里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个 id 写 Redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。

 4、比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。

阅读量:1497

点赞量:0

收藏量:0