一:确认种类

RabbitMQ的消息确认有两种。一种是消息发送确认,用来确认生产者将消息发送给交换器,交换器传递给队列的过程中消息是否成功投递。发送确认分为两步,一是确认是否到达交换器,二是确认是否到达队列。第二种是消费接收确认。确认消费者是否成功消费了队列中的消息。

二:消息发送确认

(1)ConfirmCallback
通过实现ConfirmCallBack接口,消息发送到交换器Exchange后触发回调。

使用该功能需要开启确认,spring-boot中配置如下:  spring.rabbitmq.publisher-confirms = true

(2)ReturnCallback
        通过实现ReturnCallback接口,如果消息从交换器发送到对应队列失败时触发,比如根据发送消息时指定的routingKey找不到队列时会触发。

使用该功能需要开启确认,spring-boot中配置如下:  spring.rabbitmq.publisher-returns = true

三:消息接收确认

(1)确认模式
  • AcknowledgeMode.NONE:不确认
  • AcknowledgeMode.AUTO:自动确认
  • AcknowledgeMode.MANUAL:手动确认
spring-boot中配置方法:spring.rabbitmq.listener.simple.acknowledge-mode = manual
(2)手动确认

图 未确认的消息数

上图为channel中未被消费者确认的消息数。通过RabbitMQ的host地址加上默认端口号15672访问管理界面。
(2.1)成功确认
void basicAck(long deliveryTag, boolean multiple) throws IOException;
deliveryTag:该消息的index
multiple:是否批量. true:将一次性ack所有小于deliveryTag的消息。
消费者成功处理后,调用channel.basicAck(message.getMessageProperties().getDeliveryTag(), false)方法对消息进行确认。
(2.2)失败确认
void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException;
deliveryTag:该消息的index。
multiple:是否批量。true:将一次性拒绝所有小于deliveryTag的消息。
requeue:被拒绝的是否重新入队列。
void basicReject(long deliveryTag, boolean requeue) throws IOException;
deliveryTag:该消息的index。
requeue:被拒绝的是否重新入队列。
channel.basicNack 与 channel.basicReject 的区别在于basicNack可以批量拒绝多条消息,而basicReject一次只能拒绝一条消息。
消息队列的基础知识可以参考:消息队列RabbitMQ基础知识详解

四:思考

(1)手动确认模式,消息手动拒绝中如果requeue为true会重新放入队列,但是如果消费者在处理过程中一直抛出异常,会导致入队-》拒绝-》入队的循环,该怎么处理呢?
第一种方法是根据异常类型来选择是否重新放入队列。
第二种方法是先成功确认,然后通过channel.basicPublish()重新发布这个消息。重新发布的消息网上说会放到队列后面,进而不会影响已经进入队列的消息处理。
void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException;
(2)消息确认的作用是什么?
为了防止消息丢失。消息丢失分为发送丢失和消费者处理丢失,相应的也有两种确认机制。
(3)Redis和 rabbit MQ 都可以做消息队列,为什么选择了Rabbit MQ ?
        RabbitMQ和Redis都可以做队列,但是他们还是有区别的。比如,Redis的消息队列,如果在从队列pop出去的时候,worker处理失败的话,数据不会回到队列中,需要从业务中手动把失败的处理数据push到队列中,而RabbitMQ可以自动处理失败的worker使数据不丢失;RabbitMQ还可以保证数据在传输过程中持久化,在通道和队列中的数据可以设置为持久化。另外,Redis严格来说并不是消息队列,它是一个内存数据库,不过因为其某些特性适合用来充当队列,所以也多被用于做简单的MQ, Redis之父倒是开发了个真正的消息队列disque,有兴趣可以看看。 
       相比起Redis,RabbitMQ有更加完善的MQ机制,这里我们仅讨论消息的durable(持久性),后续一系列其他机制有时间再交流。 
      RabbitMQ有一个消息确认机制来保证消息的不丢失:客户端从队列中取出消息之后,可能需要一段时间才能处理完成,如果在这个过程中,客户端出错了,异常退出了,而数据还没有处理完成,那么非常不幸,这段数据就丢失了,因为RabbitMQ默认会把此消息标记为已完成,然后从队列中移除,消息确认是客户端从RabbitMQ中取出消息,并处理完成之后,会发送一个ack告诉RabbitMQ,消息处理完成,当RabbitMQ收到客户端的获取消息请求之后,或标记为处理中,当再次收到ack之后,才会标记为已完成,然后从队列中删除。当RabbitMQ检测到客户端和自己断开链接之后,还没收到ack,则会重新将消息放回消息队列,交给下一个客户端处理,保证消息不丢失,也就是说,RabbitMQ给了客户端足够长的时间来做数据处理。 

五:消息持久化

  1. RabbitMQ在服务端没有声明队列queue持久化(durable=True)时,队列是存在内存中的,服务端down机了,队列也随之消失。
  2. RabbitMQ在服务端只声明queue持久化,但是在发送消息时,没有声明持久化(properties=pika.BasicProperties(delivery_mode=2,)),服务器down机,只保留队列,但是不保留消息。
  3. RabbitMQ在服务端声明queue持久化,并且在发消息时也声明了持久化,服务down机重启后,队列和消息都能得到保存。
  4. 服务端声明持久化,客户端想接受消息的话,必须也要声明queue时,也要声明持久化,不然的话,客户端执行会报错。
Reference:
 
 
 

Rabbit MQ 消息确认和持久化机制的更多相关文章

  1. 使用Rabbit MQ消息队列

    使用Rabbit MQ消息队列 综合概述 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息 ...

  2. rabbit MQ 消息队列

    为什么会需要消息队列(MQ)? 一.消息队列概述消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ...

  3. Spring Boot:使用Rabbit MQ消息队列

    综合概述 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程则可以 ...

  4. 快速掌握RabbitMQ(三)——消息确认、持久化、优先级的C#实现

    1 消息确认 在一些场合,如转账.付费时每一条消息都必须保证成功的被处理.AMQP是金融级的消息队列协议,有很高的可靠性,这里介绍在使用RabbitMQ时怎么保证消息被成功处理的.消息确认可以分为两种 ...

  5. Kafka分片存储、消息分发和持久化机制

    Kafka 分片存储机制 Broker:消息中间件处理结点,一个 Kafka 节点就是一个 broker,多个 broker 可以组成一个 Kafka集群. Topic:一类消息,例如 page vi ...

  6. RabbitMQ消息确认(发送确认,接收确认)

    前面几篇记录了收发消息的demo,今天记录下关于 消息确认方面的 问题. 下面是几个问题: 1.为什么要进行消息确认? 2.rabbitmq消息确认 机制是什么样的? 3.发送方如何确认消息发送成功? ...

  7. 【转】RabbitMQ基础——和——持久化机制

    这里原来有一句话,触犯啦天条,被阉割!!!! 首先不去讨论我的日志组件怎么样.因为有些日志需要走网络,有的又不需要走网路,也是有性能与业务场景的多般变化在其中,就把他抛开,我们只谈消息RabbitMQ ...

  8. RabbitMQ 消息确认机制以及lazy queue+ disk消息持久化

    一:Basic的一些属性,一些方法 1. 消费端的确认 自动确认: message出队列的时候就自动确认[broke] basicget... 手工确认: message出队列之后,要应用程序自己去确 ...

  9. SpringBoot 整合 RabbitMQ(包含三种消息确认机制以及消费端限流)

    目录 说明 生产端 消费端 说明 本文 SpringBoot 与 RabbitMQ 进行整合的时候,包含了三种消息的确认模式,如果查询详细的确认模式设置,请阅读:RabbitMQ的三种消息确认模式 同 ...

随机推荐

  1. eclipse解决maven编码UTF-8的不可映射字符

    1.同时指定<project.build.sourceEncoding>属性和<encoding>的方式可适用于Maven2和Maven3. 2.在Maven3中可以只增加&l ...

  2. [原创]基于Zynq Linux环境搭建(四)

    此篇编译根文件系统 下载busybox和dropbear, [#73#13:04:52 FPGADeveloper@ubuntu ~/Zybo_Demo/XilinxFS]$wget --no-che ...

  3. [转] Brook 搭建教程

    https://www.jiongjun.cc/technology/500.html 在搭建 brook 代理之前,首先要求你要有一台国外 vps,关于国外 vps 选择,可以参考这篇:推荐几款国外 ...

  4. numpy的array合并-【老鱼学numpy】

    概述 本节主要讲述如何把两个数组按照行或列进行合并. 按行进行上下合并 例如: import numpy as np a = np.array([1, 1, 1]) b = np.array([2, ...

  5. 关闭IIS开启自启

    关闭IIS开启自启 win+R输入services.msc 找到服务名称为World Wide Web Publishing Service 双击停止,右键禁用

  6. pycharm中replace的应用

    name = "sucanji" v = name.replace("s","L") print(v) #输出结果就是把sucanji中的s ...

  7. 2018山东省赛sequence

    2018山东省赛sequence因为必须要删除一个数,所以可以计算每个数删除的代价,从而选取代价最小的进行删除如果一个数大于它前面的所有数的最小值而小于次小值,删除最小值的代价就要+1:如果一个数本身 ...

  8. [tensorflow]图像处理相关模块的安装(python3中PIL)

    直接上过程图(平台为Anaconda): 默认已经配置完了tensorflow的3.5的环境 我这里已经安装完成 接下来,就可以在python文件中引入模块了 from PIL import Imag ...

  9. Android-SD卡相关操作

    SD卡相关操作 1.获取 App 文件目录 //获取 当前APP 文件路径 String path1 = this.getFilesDir().getPath(); 当前APP目录也就是应用的这个目录 ...

  10. java动态代理实现与原理详细分析

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...