RabbitMQ - Publisher的消息确认机制
queue和consumer之间的消息确认机制:通过设置ack。那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consumer处理呢?毕竟对于一些非常重要的数据,可能Publisher需要确认某个消息已经被正确处理。
1. 事务机制 VS Publisher Confirm
如果采用标准的 AMQP 协议,则唯一能够保证消息不会丢失的方式是利用事务机制 -- 令 channel 处于 transactional 模式、向其 publish 消息、执行 commit 动作。在这种方式下,事务机制会带来大量的多余开销,并会导致吞吐量下降 250% 。为了补救事务带来的问题,引入了 confirmation 机制(即 Publisher Confirm)。
为了使能 confirm 机制,client 首先要发送 confirm.select 方法帧。取决于是否设置了 no-wait 属性,broker 会相应的判定是否以 confirm.select-ok 进行应答。一旦在 channel 上使用 confirm.select方法,channel 就将处于 confirm 模式。处于 transactional 模式的 channel 不能再被设置成 confirm 模式,反之亦然。
一旦 channel 处于 confirm 模式,broker 和 client 都将启动消息计数(以 confirm.select 为基础从 1 开始计数)。broker 会在处理完消息后,在当前 channel 上通过发送 basic.ack 的方式对其进行 confirm 。delivery-tag 域的值标识了被 confirm 消息的序列号。broker 也可以通过设置 basic.ack 中的 multiple 域来表明到指定序列号为止的所有消息都已被 broker 正确的处理了。
在异常情况中,broker 将无法成功处理相应的消息,此时 broker 将发送 basic.nack 来代替 basic.ack 。在这个情形下,basic.nack 中各域值的含义与 basic.ack 中相应各域含义是相同的,同时 requeue 域的值应该被忽略。通过 nack 一或多条消息,broker 表明自身无法对相应消息完成处理,并拒绝为这些消息的处理负责。在这种情况下,client 可以选择将消息 re-publish 。
在 channel 被设置成 confirm 模式之后,所有被 publish 的后续消息都将被 confirm(即 ack) 或者被 nack 一次。但是没有对消息被 confirm 的快慢做任何保证,并且同一条消息不会既被 confirm 又被 nack 。
2. 消息在什么时候确认
broker 将在下面的情况中对消息进行 confirm :
- broker 发现当前消息无法被路由到指定的 queues 中(如果设置了 mandatory 属性,则 broker 会先发送 basic.return)
- 非持久属性的消息到达了其所应该到达的所有 queue 中(和镜像 queue 中)
- 持久消息到达了其所应该到达的所有 queue 中(和镜像 queue 中),并被持久化到了磁盘(被 fsync)
- 持久消息从其所在的所有 queue 中被 consume 了(如果必要则会被 acknowledge)
broker 会丢失持久化消息,如果 broker 在将上述消息写入磁盘前异常。在一定条件下,这种情况会导致 broker 以一种奇怪的方式运行。例如,考虑下述情景:
1. 一个 client 将持久消息 publish 到持久 queue 中
2. 另一个 client 从 queue 中 consume 消息(注意:该消息具有持久属性,并且 queue 是持久化的),当尚未对其进行 ack
3. broker 异常重启
4. client 重连并开始 consume 消息
在上述情景下,client 有理由认为消息需要被(broker)重新 deliver 。但这并非事实:重启(有可能)会令 broker 丢失消息。为了确保持久性,client 应该使用 confirm 机制。如果 publisher 使用的 channel 被设置为 confirm 模式,publisher 将不会收到已丢失消息的 ack(这是因为 consumer 没有对消息进行 ack ,同时该消息也未被写入磁盘)。
3. 编程实现
首先要区别AMQP协议mandatory和immediate标志位的作用。
mandatory和immediate是AMQP协议中basic.pulish方法中的两个标志位,它们都有当消息传递过程中不可达目的地时将消息返回给生产者的功能。具体区别在于:
1. mandatory标志位
当mandatory标志位设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返还给生产者;当mandatory设为false时,出现上述情形broker会直接将消息扔掉。
2. immediate标志位
当immediate标志位设置为true时,如果exchange在将消息route到queue(s)时发现对应的queue上没有消费者,那么这条消息不会放入队列中。当与消息routeKey关联的所有queue(一个或多个)都没有消费者时,该消息会通过basic.return方法返还给生产者。
RabbitMQ - Publisher的消息确认机制的更多相关文章
- springboot + rabbitmq 用了消息确认机制,感觉掉坑里了
本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷KPI ...
- (转)RabbitMQ消息队列(九):Publisher的消息确认机制
在前面的文章中提到了queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consum ...
- RabbitMQ消息队列(九):Publisher的消息确认机制
在前面的文章中提到了queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consum ...
- RabbitMQ (十二) 消息确认机制 - 发布者确认
消费者确认解决的问题是确认消息是否被消费者"成功消费". 它有个前提条件,那就是生产者发布的消息已经"成功"发送出去了. 因此还需要一个机制来告诉生产者,你发送 ...
- RabbitMQ 消费者的消息确认机制
消息确认的几点说明: 1. Basic.Ack 发回给 RabbitMQ 以告知,可以将相应 message 从 RabbitMQ 的消息缓存中移除.2. Basic.Ack 未被 consumer ...
- SpringBoot集成RabbitMQ并实现消息确认机制
原文:https://blog.csdn.net/ctwy291314/article/details/80534604 RabbitMQ安装请参照RabbitMQ应用 不啰嗦直接上代码 目录结构如下 ...
- 消息队列RabbitMQ(三):消息确认机制
引言 RabbitMQ的模型是生产者发送信息到 Broker (代理),消费者从 Broker 中取出信息.但是生产者怎么知道消息是否真的发送到 Broker 中了呢?Broker 又怎么知道消息到底 ...
- RabbitMQ 消息确认机制
消息确认机制 在之前异常处理部分就已经写了,对于consumer的异常退出导致消息丢失,可以时候consumer的消息确认机制.重复的就不说了,这里说一些不一样的. consumer的消息确认机制 当 ...
- RabbitMQ学习笔记之五种模式及消息确认机制
本文详细介绍简单模式Simple.工作模式Work.发布订阅模式Publish/Subscribe.Topic.Routing. Maven依赖引用 <dependencies> < ...
随机推荐
- iOS8使用TouchID
iOS8新增了LocalAuthentication框架,用于TouchID的授权使用.亲測,眼下须要用户的设备支持指纹识别并已设置锁屏,并且实际測试过程中反馈比較慢.不能直接跟第三方账号passwo ...
- asm volatile ("B .")
在开发中,我们常常会有有这种需求,就是在某段代码处開始,一步一步往下跟踪调试,有人说加个while(1)循环,事实上这个循环增加后,其后边的代码就会被优化掉,达不到我们的目的,更好的办法是在须要的地方 ...
- Memento - 备忘录模式
定义 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 案例 比方如今有一个画图系统,我们在Viewer里面画了一些图形,可是在绘 ...
- ShadowDOM
HTML5 ShadowDOM & CustomElements KeKeMars 关注 2015.12.09 15:20* 字数 1239 阅读 1626评论 2喜欢 2 Web组件由四部分 ...
- Servlet+JSP 原理
Servlet是用Java编写的Server端程序,与协议和平台无关,可移植行较强. Servlet在编辑时须要导入特定的Servlet API 的包,类似于普通Java程序的写法. Servlet採 ...
- selenium iframe 定位 qq空间说说
selenium iframe 定位 qq空间说说
- WinForm里面连接Oracle数据库
WinForm里面连接Oracle数据库 string oradb = "Data Source=(DESCRIPTION=" + "(ADDRE ...
- Java 基础 —— 注解
注解(annotation)不是注释(comment): 注解,是一种元数据(metadata),可为我们在代码中添加信息提供了一种形式化的方法.注解在一定程度上实现了元数据和源代码文件的结合,而不是 ...
- linux下的C语言开发 进程创建 延伸的几个例子
在Linux下面,创建进程是一件十分有意思的事情.我们都知道,进程是操作系统下面享有资源的基本单位.那么,在linux下面应该怎么创建进程呢?其实非常简单,一个fork函数就可以搞定了.但是,我们需要 ...
- 昆石VOS3000_2.1.2.0完整安装包及安装脚本
安装包下载地址 http://www.51voip.org/post/57.html 安装教程: 上传安装包 ·给整个目录授权 chmod 777 /root/vosintsall 1.安装前准备 首 ...