MQ高级
消息队列中存在的问题
①消息可靠性:消息至少被消费一次
②延迟消息问题:消息如何延迟投递
③高可用问题:如何避免单点mq故障而导致不可以的问题
④消息堆积问题:如何解决数百万消息堆积,无法消费的问题
消息可靠性
丢失的原因:只要有消息传递,就可能会存在消息的丢失
①生产者发消息没有发送给exchange交换机
②消息到了exchange中未送达到queue
③mq宕机 ,queue将消息丢失
④consumer接收到了queue队列传来的消息,但是未消费就出现了宕机
解决方法:
①生产者确认机制
②mq持久化
③消费者确认机制
④失败重试机制
1、生产者确认机制
必须给每一个消息指定唯一的id,消息发送到mq之后,会返回一个结果给消费者,表示消息是否消费成功。
消息成功投递到交换机返回ack,未成功返回nack。
- publish-confirm-type:开启public-confirm(simple:同步等待confirm结果,correlated:异步回调,定义confirmCallBack)
消息成功投递到交换机,返回ack,未成功返回nack - publish-returns:开启publish-return功能,定义ReturnCallback
消息投递到交换机了,但是 没有路由到队列。返回ack,及路由失败原因。 - template.mandatory:路由失败时的策略。true:调用ReturnCallback false:直接丢弃消息
publisher-confirm-type: correlated #simple同步等待 correlated:异步回调
publisher-returns: true
template:
mandatory: true #定义消息路由失败策略 true :调用ReturnCallBack false:直接丢弃消息
消息持久化
如果突然宕机可能造成消息的丢失,确保消息在mq中安全保存,必须开启消息持久化机制。
①交换机持久化
@Bean
public DirectExchange simpleExchange(){
//交换机名称、是否持久化、当没有queue与其绑定时是否自动删除
return new DirectExchange("simple.direct", true, false);
②队列持久化
@Bean
public Queue simpleQueue(){
// 使用QueueBuilder构建队列,durable就是持久化的
return QueueBuilder.durable("simple.queue").build();
③消息持久化
消费者确认机制
mq投递消息给消费者,消费者获取消息后,返回ack给rabbitMQ,MQ删除消息,消费者宕机,消息未处理。
包含三种模式
none模式:消息投递是不可靠的,可能会存在丢失
auto模式:类似事务机制,出现异常时返回nack,消息回滚到mq,没有异常返回ack
manual:自己根据业务情况,去判断是否返回ack
消费失败重试机制
Spring中的retry机制,在消费者出现异常时进行重试
配置内容:
spring:
rabbitmq:
listener:
simple:
retry:
enabled: true # 开启消费者失败重试
initial-interval: 1000 # 初识的失败等待时长为1秒
multiplier: 1 # 失败的等待时长倍数,下次等待时长 = multiplier * last-interval
max-attempts: 3 # 最大重试次数
stateless: true # true无状态;false有状态。如果业务中包含事务,这里改为false
死信交换机
什么时候会出现死信:
①消息被拒绝或者是返回nack
②消息超时未消费
③队列满了
TTL:存活时间
存活时间结束 还未消费的时候 就会变成死信
(消息本身所在的队列设置了存活时间)
消息超时的两种方法:
①给队列设置ttl属性:进入队列之后超过ttl时间的消息变成死信
②给消息设置ttl属性:队列接收到消息后超过设置的存活时间就会变成死信