消息中间件终于找到解决方案了

41 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第31天,点击查看活动详情

程序在生产数据,消息端给MQ发送的这个阶段,生产者宕机了。这个时候生产者这条消息就会丢失。因为程序重启好之后可能不会再次生产该消息。

生产者丢失消息

解决方案

  • 针对上述情况mq也提供了两种方法解决。
  • 1、开启rabbitmq事务(同步)
  • 2、开启confirm模式(异步)

消费者丢失信息

  • 消费端如果没有单独设置的话默认就是MQ不管理。换句话说MQ只负责发送消息。mq为我们提供了三种模式 NONE, MANUAL, AUTO; 默认的

  • 我们需要手动将连接工厂设置MANUAL后再接收到消息后我们需要手动确认,mq才会删除消息。否则会一直等待到消费端重启才会进行重新分发数据

  • channel.basicAck(long,boolean); 确认收到消息,消息将被队列移除,false只确认当前consumer一个消息收到,true确认所有consumer获得的消息。

  • channel.basicNack(long,boolean,boolean); 确认否定消息,第一个boolean表示一个consumer还是所有,第二个boolean表示requeue是否重新回到队列,true重新入队。

  • channel.basicReject(long,boolean); 拒绝消息,requeue=false 表示不再重新入队,如果配置了死信队列则进入死信队列。

  • 其实通过rabbitmq的事务并不能解决上面的丢失情况。但是加上事务会保证消息发送的可靠性。上面发送消息后出异常这时候我们就没法回退消息了。但是事务可以帮我们实现

  • 最终测试效果是mq没有收到消息的。

  • 上面使用了两种确认方式,前者是同步确认,后者是异步确认。因为在同一个方法里。msg都是能获取到的。所以在ConfimListener中就没有返回消息。

数据退回监听

  • 上面两种一个增加安全可靠性。一个增加确认机制。还有一种情况是数据回退。当交换机没有队列绑定是这个时候发送数据后如果设置了回退属性,那么消息会回退到监听器汇中的。channel中的mandatory表示是否检测分发到队列中。

MQ丢失信息

  • 在发送消息到MQ时我们可以设置消息属性是否为可持久化。如果设置了直接就会存储在磁盘上。在内存可用时也会同步到内存中提高效率。如果消息属性中设置的是非持久化的话,就会直接存储在内存里,当内存不足是会将数据备份至磁盘上。

当消息回滚到消息队列时,这条消息不会回到队列尾部,而是仍是在队列头部,这时消费者会又接收到这条消息,如果想消息进入队尾,须确认消息后再次发送消息。