一、rabbitmq有序性
- 将消息放到同一个交换机,此交换机仅一个队列并且此队列仅只有一个消费者
- 如果想达到高效率消费,可以将消息放到同一个交换机,此交换机有多个队列并且每个队列仅只有一个消费者,每个消息体还必须都有一个全局的有序标识
二、rabbitmq持久化
为了保证RabbitMQ在退出或者宕机等异常情况下数据没有丢失,需要将queue,exchange和Message都持久化。仅仅只是想消息不被丢失,可以只用持久化queue,Message。但如果RabbitMQ宕机重启后正常运行没有持久化exchange,那么生产者此时无法发送消息到RabbitMQ上,因为RabbitMQ服务重启之后,exchange将不复存在了,所以一般都会持久化。
三、rabbitmq确认机制
确认机制分为两个方面,一个是消息发送确认,另一个是消息消费确认机制。
- 发送确认: 发送确认机制中有两个回调函数。一个回调函数是ConfirmCallback用来确认消息是否发送到exchange(交换器)中;另一个回调函数是ReturnCallback用来确认消息是否发送到queue(队列)中。此处的ReturnCallback回调函数注意延迟消息此时还没到queue,还在exchange中,所以此方法要排除延迟类型消息。
- 消费确认: 消费确认机制又分手动确认和自动确认两种模式
- 手动确认:调用api对MQ发送ACK(确认);手动确认的方式有三种:ACK(确认)、NACK(不确认)、Reject(拒绝);其中NACK和Reject都是拒绝消费的意思,拒绝后的消息都可以选择重新入队列被再次消费,如果被拒的消息选择不再消费时,此消息会被放到死信队列中,NACK和。区别在于NACK可以一次拒绝多条而Reject一次只能拒绝一条。
- 自动确认:当消费方法没有异常时会自动对MQ发出CK(确认);若出现异常,会对MQ发出nack,消息会重回队列。
四、rabbitmq幂等性
幂等性的意思是对于同一操作发起的一次请求或者多次请求的结果是一致的,幂等性可以保障重复消费问题。解决方案:每个消息用一个唯一标识来区分,消费前先判断标识有没有被消费过,若已消费过,则直接ACK。
五、rabbitmq可靠性方案及详情
方案一:开启事务(不推荐,效率差)
方案二:开启confirm(推荐,此处详解此方案)
- 开启RabbitMQ持久化(交换机、队列、消息)
- 关闭RabbitMQ自动ACK,改为手动ACK
- 保证投放消息不丢失:
- 当每次业务处理完后要投送消息前将自定义的消息对象存到数据库中(redis性能更高),自定义消息对象主要包涵:消息唯一id、投送状态(投送中、投送成功、投送失败)、投送过期时间、投送重试次数、接收状态(接收中、接收成功、接收失败)、接收重试次数。
- 当ConfirmCallback回调函数触发时,如果已确认则标记为“投送成功”,否则标记为“投送失败”,ReturnCallback回调触发如果是非延迟消息则也标记为“投送失败”。
- 最后有一个专门的定时任务每个3分钟扫描自定义消息对象数据,查询出投送中并且投送过期时间小于当前时间的消息对象,将这些消息对象重新投递,一条消息最多被重新投递三次,若投递了三次仍然失败,则记录到数据库,不会再投递,需要人工干预处理,并将消息标记为“投送失败”。
- 保证消费消息不丢失:
- 消费者取到消息后,从消息中取出唯一标识,先判断此消息有没有被消费过,若已消费过,则直接ACK(避免重复消费)
- 正常消费消息后,将数据库中自定义的消息对象数据的接收状态改为“接收成功”,并手动ACK告诉MQ此消息已成功消费
- 遇到异常时,捕获异常,将消费消息拒绝后重新入列消费,若超过接收重试次数则标记为“接收失败”,并手动ACK告诉MQ此消息已成功消费,最后人工干预处理