RabbitMQ消息应答与持久化

RabbitMQ消息应答

1、执行一个任务可能需要花费几秒钟,你可能会担心如果一个消费者在执行任务过程中挂掉了。基于现在的代码,一旦RabbitMQ将消息分发给了消费者,就会从内存中删除。在这种情况下,如果杀死正在执行任务的消费者,会丢失正在处理的消息,也会丢失已经分发给这个消费者但尚未处理的消息。

但是,我们不想丢失任何任务,如果有一个消费者挂掉了,那么我们应该将分发给它的任务交付给另一个消费者去处理

为了确保消息不会丢失,RabbitMQ支持消息应答。消费者发送一个消息应答,告诉RabbitMQ这个消息已经接收并且处理完毕了。RabbitMQ可以删除它了。

如果一个消费者挂掉却没有发送应答,RabbitMQ会理解为这个消息没有处理完全,然后交给另一个消费者去重新处理。这样,你就可以确认即使消费者偶尔挂掉也不会不丢失任何消息了。

没有任何消息超时限制;只有当消费者挂掉时,RabbitMQ才会重新投递。即使处理一条消息会花费很长的时间

消息应答是默认打开的。我们明确地把它们关掉了(autoAck=true)。现在将应答打开,一旦我们完成任务,消费者会自动发送消息应答。

  1. boolean autoAck = false;
  2. channel.basicConsume(QUEUE_NAME, autoAck, consumer);

RabbitMQ持久化

  1. **持久化是为提高rabbitmq消息的可靠性,防止在异常情况(重启,关闭,宕机)下数据的丢失**

rabbitmq持久化分为三个部分: 交换器的持久化、队列的持久化和消息的持久化

1、交换器的持久化

交换器的持久化是通过声明队列时,将durable参数设置为true实现的。如果交换器不设置持久化,那么rabbitmq服务重启之后,相关的交换器元数据将会丢失,不过消息不会丢失,只是不能将消息发送到这个交换器中了,建议将交换器设置为持久化

设置交换器的持久化

  1. // 三个参数分别为 交换器名、交换器类型、是否持久化
  2. channel.exchangeDeclare(EXCHANGE_NAME, "topic", true);

2、队列的持久化

队列的持久化是通过声明队列时,将durable参数设置为true实现的。如果队列不设置持久化,那么rabbitmq服务重启之后,相关的队列元数据将会丢失,而消息是存储在队列中的,所以队列中的消息也会被丢失

设置队列的持久化

  1. // 参数1 queue :队列名
  2. // 参数2 durable :是否持久化
  3. // 参数3 exclusive :仅创建者可以使用的私有队列,断开后自动删除
  4. // 参数4 autoDelete : 当所有消费客户端连接断开后,是否自动删除队列
  5. // 参数5 arguments
  6. channel.queueDeclare(QUEUE_NAME, true, false, false, null);

3、消息的持久化

队列的持久化只能保证其队列本身的元数据不会被丢失,但是不能保证消息不会被丢失。所以消息本身也需要被持久化,可以在投递消息前设置AMQP.BasicProperties的属性deliveryMode为2即可:

  1. // 参数1 exchange :交换器
  2. // 参数2 routingKey : 路由键
  3. // 参数3 props : 消息的其他参数,其中 MessageProperties.PERSISTENT_TEXT_PLAIN 表示持久化
  4. // 参数4 body : 消息体
  5. channel.basicPublish("", queue_name, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

4、问题

描述:将交换器、队列和消息都设置持久化之后就能保证数据不会被丢失吗?当然不是,多个方面:

  • 消费者端: 消费者订阅队列将autoAck设置为true,虽然消费者接收到了消息,但是没有来得及处理就宕机了,那数据也会丢失,解决方案就是以手动确认接收消息,待处理完消息之后,手动删除消息
  • 在rabbitmq服务端,如果消息正确被发送,但是rabbitmq未来得及持久化,没有将数据写入磁盘,服务异常而导致数据丢失,解决方案,可以通过rabbitmq集群的方式实现消息中间件的高可用性

发表评论

表情:
评论列表 (有 0 条评论,26人围观)

还没有评论,来说两句吧...

相关阅读

    相关 RabbitMQ--消息应答

    一、概念 1、概念 消费者完成一个任务可能需要一段时间,如果其中一个消费者处理一个长的任务并只完成了部分突然他就挂了,此时消息就会丢失。为了保证消息在发送过程中不丢