最近阅读了rabbitmq的官方文档,然后结合之前面试时被问到关于消息队列的问题来探索一下关于消息队列的消息确认机制。

  其实消息确认就是消费者确认消息被消费了, 生产者确认消息已经发送到了消息队列中了。

  我们知道rabbitmq有四种消息机制,下图是为了我们对消息确认的理解从官网盗了一张工作队列的图如下:

一、 关于消费者确认方面问题

  在我们的mq推送了消息给消费者后,我们怎么知道消息被消费者消费了呢?万一消费者没有消费该消息,或者消费者挂了,这消息是不是就永久丢失了,所以根据此有下列几个关于消费者确认的相关问题。同时在这我们也纠正一个常见的误区,mq是推消息到消费者处的而不是消费者去mq中取消息的,然后在mq中消息充足的情况下,mq推消息给消费者不是等消费者消费完一个再推一个,而是根据 prefetch_count参数来决定可以推多个消息到消费者的缓存里面。

问题1: 如果其中一个消费者开始一项漫长的任务,而仅部分完成而死掉,会发生什么情况。使用我们当前的代码,RabbitMQ一旦将消息传递给消费者,便立即将其标记为删除。在这种情况下,如果您杀死一个work,我们将丢失正在处理的消息。我们还将丢失所有发送给该特定工作人员但尚未处理的消息。

答:为了确保消息永不丢失,RabbitMQ支持 消息确认。消费者发送回一个确认(acknowledgement)以告知RabbitMQ已经接收,处理了特定的消息,然后RabbitMQ会去删除这条消息,如果消费者在不发送确认的情况下死亡(其通道已关闭,连接已关闭或TCP连接丢失),RabbitMQ将了解消息未得到充分处理,并将重新排队。如果同时有其他消费者在线,它将很快将其重新分发给另一个消费者。这样,您可以确保即使工人偶尔死亡也不会丢失任何消息

问题2:开启了消息持久化,消息就一定不会丢失吗?

答: 将消息标记为持久性并不能完全保证不会丢失消息。尽管它告诉RabbitMQ将消息保存到磁盘,但是仍有很短的时间RabbitMQ接受了消息但尚未将其保存。另外,RabbitMQ不会对每条消息都执行fsync(2)-它可能只是保存到缓存中,而没有真正写入磁盘。持久性保证并不强,但是对于我们的简单任务队列而言,这已经绰绰有余了。如果您需要更强有力的保证,则可以使用 发布者确认

  在这里补充一个知识:如果mq开启了持久化以后, 生产者把消息推给消息队列, 消息队列会复制一份消息到持久化队列,然后有新线程从持久化队列中把消息持久化到磁盘中。

问题3: 两个消费者同时消费一个队列,是队列分发消息还是消费者去取消息?

答:您可能已经注意到,调度仍然无法完全按照我们的要求进行。例如,在有两名工人的情况下,当有的消息都很重,有的消息消息很轻时,一位工人将一直忙碌而另一位工人将几乎不做任何工作。好吧,RabbitMQ对此一无所知,并且仍将平均分配消息。

发生这种情况是因为RabbitMQ在消息进入队列时才调度消息。它不会查看使用者的未确认消息数。它只是盲目地将每第n条消息发送给第n个使用者。
为了解决这个问题,我们可以将Channel#basic_qos通道方法与 prefetch_count = 1设置一起使用。这使用basic.qos协议方法来告诉RabbitMQ一次不向工作人员发送多条消息。换句话说,在处理并确认上一条消息之前,不要将新消息发送给工作人员。而是将其分派给不忙的下一个工作程序。
 
  这里补充一个知识:当两个消费者同时订阅了同一个队列时,队列会把消息循环平均分配给两个消费者。

问题4: 关于队列大小的注意事项,如果队列满了怎么处理?

答:如果队列满了以后,我们一方面可以增加消费者的数量,很浅显消费者越多消费消息就越快,还有一个是设置消息的过期时间来控制。

  这里补充个知识: 当消息过期或者被消费者拒绝并且设置不返回队列中,这消息将加入死信队列。

二、关于生产者确认方面问题

  同样的,我们的生产者给mq push消息的时候,我们怎么知道这消息放进了mq里面了呢?所以这引发了mq确认消息的相关问题。

问题1: 发布者确认消息机制是怎样的?

答:首先消息的传递机制是这样,发布者将消息发送到消息队列的exchange中,然后根据exchange的分发规则,分发到制定具体队列,如果开启了持久化,消息会复制一份持久化队列中, 持久化队列在收到消息后会给队列返回ack确认信息, 然后队列给exchange返回确认信息, exchange根据回调函数给发布者返回确认信息,这样发布者确认就算完成了。

  当时你知道发布者的确认规则,你是不是立马想到确认要经过这么多个中间人,省略中间的环节行不行勒,哈哈答案是可以的,不过得自己去改造啦,这是性能优化的一项。

问题2:发布者确认的方式有哪几种?

答:有三种确认方式

1)同步确认,消息发出后一直处于阻塞状态等待确认消息,可以设置超时时间,如果超过超时时间则认为消息丢失, 如果超时或者消息确认失败则会抛出异常,我们捕获异常然后选择是重发还是等其他处理方式。

2)批量确认,一次性发出一批消息然后阻塞等待,形式和同步确认相似,有点则是一批确认所以性能上会有很大的提升,缺点是我们不能确认具体发生了什么错误,并且我们得在内存中存储这批消息以确认发送成功的消息和重发失败的消息。

3)异步确认,发送消息后注册一个回调函数,不阻塞线程,在消息确认后会调用回调函数

  如果想更详细地了解其机制可以阅读其官方文档,文档中有关于消息确认的具体代码展示,可以更方便地理解其机制。

RabbitMq之消息确认的更多相关文章

  1. Java使用RabbitMQ之消息确认(confirm模板)

    RabbitMQ生产者消息确认Confirm模式,分为普通模式.批量模式和异步模式,本次举例为普通模式. 源码: package org.study.confirm4; import com.rabb ...

  2. RabbitMQ的消息确认机制

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

  3. RabbitMq初探——消息确认

    消息确认机制 前言 消息队列的下游,业务逻辑可能复杂,处理任务可能花费很长时间.若在一条消息到达它的下游,任务刚处理了一半,由于不确定因素,下游的任务处理进程 被kill掉啦,导致任务无法执行完成.而 ...

  4. RabbitMQ学习笔记六:RabbitMQ之消息确认

    使用消息队列,必须要考虑的问题就是生产者消息发送失败和消费者消息处理失败,这两种情况怎么处理. 生产者发送消息,成功,则确认消息发送成功;失败,则返回消息发送失败信息,再做处理. 消费者处理消息,成功 ...

  5. RabbitMQ 之消息确认机制(事务+Confirm)

    概述 在 Rabbitmq 中我们可以通过持久化来解决因为服务器异常而导致丢失的问题,除此之外我们还会遇到一个问题:生产者将消息发送出去之后,消息到底有没有正确到达 Rabbit 服务器呢?如果不错得 ...

  6. RabbitMQ (十一) 消息确认机制 - 消费者确认

    由于生产者和消费者不直接通信,生产者只负责把消息发送到队列,消费者只负责从队列获取消息(不管是push还是pull). 消息被"消费"后,是需要从队列中删除的.那怎么确认消息被&q ...

  7. springboot整合rabbitmq,支持消息确认机制

    安装 推荐一篇博客https://blog.csdn.net/zhuzhezhuzhe1/article/details/80464291 项目结构 POM.XML <?xml version= ...

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

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

  9. RabbitMQ的消息确认ACK机制

    1.什么是消息确认ACK. 答:如果在处理消息的过程中,消费者的服务器在处理消息的时候出现异常,那么可能这条正在处理的消息就没有完成消息消费,数据就会丢失.为了确保数据不会丢失,RabbitMQ支持消 ...

随机推荐

  1. 数据可视化之powerBI入门(十三)CALCULATE函数的最佳搭档:FILTER

    https://zhuanlan.zhihu.com/p/64383000 介绍过CALCULATE函数之后,有必要再介绍它的最佳搭档:FILTER函数. CALCULATE函数的第二个及之后的参数是 ...

  2. 机器学习实战基础(二十二):sklearn中的降维算法PCA和SVD(三) PCA与SVD 之 重要参数n_components

    重要参数n_components n_components是我们降维后需要的维度,即降维后需要保留的特征数量,降维流程中第二步里需要确认的k值,一般输入[0, min(X.shape)]范围中的整数. ...

  3. 从对象到类,Java中需要知道的这些东西

    1. 对象的诞生   在平时的开发中,我们使用对象的时候,都是直接new一个临时变量然后进行各种逻辑赋值然后返回,但是你有没有想过一个对象在创建的过程中经历了什么呢,为什么创建时静态变量就已经赋完值了 ...

  4. 【运维--安全相关】cerbot证书自动化续期

    前言 Certbot可以配置为在证书过期之前自动更新证书.由于Let’s Encrypt SSL证书有效期时间为90天,所以建议您利用此功能.您可以通过运行以下命令来测试证书的自动续订: 安装 yum ...

  5. Ethical Hacking - GAINING ACCESS(6)

    Server Side Attack Analysing scan results and exploiting target system. Go to the Analysis page and ...

  6. [CISCN2019 华东南赛区]Double Secret

    0x01 进入页面如下 提示我们寻找secret,再加上题目的提示,猜测这里有secret页面,我们尝试访问,结果如下 根据它这个话的意思,是让我们传参,然后它会给你加密,我们试一下 发现输入的1变成 ...

  7. 【JVM之内存与垃圾回收篇】方法区

    方法区 前言 这次所讲述的是运行时数据区的最后一个部分 从线程共享与否的角度来看 ThreadLocal:如何保证多个线程在并发环境下的安全性?典型应用就是数据库连接管理,以及会话管理 栈.堆.方法区 ...

  8. Shell基本语法---处理海量数据的cut命令

    cut命令 cut应用场景:通常对数据进行列的提取 语法:cut [选项] [file] -d #指定分割符 -f #指定截取区域 -c #以字符为单位进行分割 # 以':'为分隔符,截取出/etc/ ...

  9. java8之Stream流处理

    简介 Stream 流处理,首先要澄清的是 java8 中的 Stream 与 I/O 流 InputStream 和 OutputStream 是完全不同的概念. Stream 机制是针对集合迭代器 ...

  10. 《闲扯Redis六》Redis五种数据类型之Hash型

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...