最近阅读了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. scala 数据结构(十):折叠、扫描、拉链(合并)、迭代器

    1 折叠 fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历. 1)可以把reduceLeft看做简化版的foldLeft. 如何理解: def redu ...

  2. java 基本语法(十六)Lambda (三)函数式接口

    方法引用1.理解:方法引用可以看做是Lambda表达式深层次的表达.换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法. 2.使用情境:当要传递给Lam ...

  3. Redis之字典

    概念 字典,又称为符号表.关联数组或映射(map),是一种用于保存键值对(key-value pair)的抽象数据结构.字典中每个键都是独一无二的,程序可以根据键来更新值,或者删除整个键值对. 用途 ...

  4. Python Ethical Hacking - ARP Spoofing

    Typical Network ARP Spoofing Why ARP Spoofing is possible: 1. Clients accept responses even if they ...

  5. metaspolit下UAC提权以及日志清除

    在获得webshell时但权限不够大,这时候为了完全获得受害者机器的权限,使用msf进行后渗透. 一.获取Meterpreter会话 Meterpreter 是msf的一个payload,目标执行之后 ...

  6. sqlserver——merge用法

    merge集插入,更新,删除于一体,如果要对一个表同时进行插入,更新,删除2个或3三个操作.效率要高于单个操作. merge into tableb b --被操作表using (select id, ...

  7. PHP中使用 TUS 协议来实现可恢复文件上传

    曾经尝试过用PHP上传大文件吗?想知道您是否可以从上次中断的地方继续上传,而不会在遇到任何中断的情况下再次重新上传整个数据?如果您觉得这个场景很熟悉,请接着往下阅读. 文件上传是我们几乎所有现代Web ...

  8. Java中使用断言

    由于断言在Java程序中用于开发和测试阶段,考虑到以后很有可能会用到,在此先记类一下. 在Java语言中,给出了3种处理系统错误的机制: 1.抛出一个异常 2.日志 3.使用断言 什么时候使用断言呢? ...

  9. 题解 洛谷 P2280 【[HNOI2003]激光炸弹】

    这道题因为要求价值最大值,所以正方形应尽可能多覆盖目标,因此所得的正方形四个顶点一定在格点上. 经过分析后,我们就可以知道,该题做法就是用二维前缀和进行事前预处理,然后一个一个枚举每个点覆盖到的总价值 ...

  10. Presto性能调优的五大技巧

    概述 Presto架构 Presto是一个分布式的查询引擎,本身并不存储数据,但是可以接入多种数据源,并且支持跨数据源的级联查询. Presto的架构分为: Coodinator:解析SQL语句,生成 ...