消息可靠性保证
MQ消息可靠性可以从三个层面进行保证;
生产者层面:
- 配置连接重试机制,避免因为短暂的网络问题导致发送消息失败。
- 开启
Publisher Confirm
和Publisher Return
机制。
通过配置Confrim和Return回调逻辑,根据消息是否成功发送进行相应回调业务逻辑处理,如失败消息保存到数据库,配置定时任务,重新发送,如达到最大发送失败次数,在进行消息通知响应人员进行人工干预排查处理。
Confirm:用来判断消息是否被成功投递到交换机,投递成功返回ack,失败返回nack;生产者生产消息时,为每个消息自定义ConfirmCallback逻辑。
Return:用来确认消息是否被成功路由到队列,如果路由到队列失败触发;
Return
回调机制只能配置一个,可以在配置类统一定义路由失败回调。
MQ层面:
开启交换机、队列(durable = true),消息(deliveryMode = 2)持久化机制。使用Spring AMQP
消息队列框架进行消息处理时,声明的交换机、队列,以及发送的消息,默认是开启持久化的。
消费者层面:
- 配置消费确认机制;
SpringAMQP
支持自动确认(auto)、手动确认(manual)、不处理(none)三种消息确认处理模式。一般都是通过auto处理消息确认。消费成功返回ack,MQ删除消息;失败返回nack,消息重回队列 进行再投递;消费者处理失败并拒绝reject,MQ删除消息。
- 配置消费失败本地重试机制;
为避免消息无限重回队列再投递,可以配置本地重试机制,达到最大重试次数,通过自定义重试次数耗尽后的消息处理策略,确保消息不丢失。
一般选择将失败消息投递到指定交换机,路由到指定队列,通过监听队列中的失败消息,存入数据库消息表,搭配定时任务进行再消费处理。
消息幂等性操作
消息操作幂等性:同一条消息被重复消费时,业务处理的结果与仅消费一次时的结果相同。
解决方案:
- 为消息设置唯一ID,消费时进行判断处理。
- 利用数据库唯一索引,适合保证插入操作幂等性处理。
RabbitMQ实现延迟队列的两种方式
延迟队列的应用场景:订单超时未支付、限时任务处理等。
RabbitMQ本身不支持延迟队列,但可以通过以下两种方式,实现消息延迟消费功能。
死信队列+TTL(Time To Live)
消息正常路由到指定队列,通过在消息头设置消息过期时间、或声明队列时指定消息过期时间(RabbitMQ默认以最小的为准),消息存活时间到期未被消费,成为死信。
为队列绑定死信交换机,消息存活时间到期自动投递到死信交换机指定的队列。
通过监听死信交换机对应的队列中的信息,完成消息延迟消费。
延迟消息插件
RabbitMQ社区提供了一个延迟消息插件来实现相同的效果。
安装延迟消息插件;
生产者发送消息时通过消息后置处理器,指定消息延迟时间; 监听器绑定延迟交换机(delayed = "true"),表示到达延迟时间后,消息被消费。