事务&生产者确认

一般情况下,生产者将消息发送后,继续进行别的业务逻辑处理。消息从生产者发送后,可能由于网络原因丢失,也可能因为RabbitMQ服务端奔溃未被处理...总之,对于

消息是否安全到达服务器,生产者一无所知。在一些场景下,这也许是可行的,毕竟丢失消息的几率较小,丢失几条消息也并不会产生严重的后果;在另外一些场景,需要生产

者确认消息到达服务端,或者得知消息未到达服务端的情况以做出相应的处理。在RabbitMQ中,生产者可以通过两种方式达到上述目的:事务和生产者确认。

事务

RabbitMQ事务的概念并不模式,与数据库事务大同小异。在RabbitMQ中,客户端开启事务,之后开始发送消息,此时的消息并未达到服务端,直到提交事务,如果事务提交成功,则之前发送的消息被

发送的服务端,否则服务端抛出异常,我们捕获该异常并进行事务回滚。

事务机制是在AMQP协议层面支持的,对应到RabbitMQ中,通过以下方法进行支持:

channel.txSelect() //将信道置为信道模式,开启事务
channel.txCommit() //提交事务
channel.txRollback() //回滚事务

事务的一般使用方式如下:

channel.txSelect(); //开始事务
try {
channel.basicPublish("txExchange","",null,"m3".getBytes()); //发送一条或多条消息
//...
channel.txCommit(); //提交事务
}catch (Exception e){
e.printStackTrace();
channel.txRollback(); //回滚事务
}

事务纵然可以保证生产者消息到达服务端,然而这是以性能为代价的。事务会阻塞发送方,直到RabbitMQ回应后,才可以继续发送消息,大量的使用事务机制会严重拖垮服务端的性能。

发送方确认

与事务机制相比,发送方确认显得更加轻量级。

在发送方确认机制中,发送方发送完消息后,继续别的业务处理;服务端稍后会发送给发送方ack或者nack消息,表明服务端已经接收到来消息还或者由于自身原因无法处理消息;发送方接收到

服务端到响应后,进行响应的处理。可见,发送方确认机制采用来一中异步的处理方式。

问题在于,发送方和服务端如何唯一确定一条消息呢?如果服务端返回了ack响应,它是对哪条消息的ack呢?也就是说在发送方确认机制下,需要来标志一条消息的唯一性。

一旦开启来发送方确认机制,信道上的发送消息将被从1编号,每条消息都将拥有一个唯一都编号,之后服务端响应时,使用deliveryTag来告诉发送方,它响应都是哪一条消息。

需要注意的是,编号是channel级别的,这样做能保证消息编号唯一性的关键在于,channel不是多线程共享的,发送方应该使用单一线程在channel发送消息来保证消息编号的唯一性,之后再

在该channel处理服务端的响应。

尽管消息被在channel上自动编号,但这只是RabbitMQ服务端和发送方确定消息唯一性的手段。对于业务而言,如果收到一条服务端的nack响应,告诉发送方eliveryTag=5,

发送方如何处理呢?也许它需要重新发送消息,但它只知道deliveryTag=5,5号消息是什么消息呢?也就是说,仍然需要客户端维护消息状态,使用发送方确认机制时,

发送方仍然可能需要维护一个消息的集合,记录已经被发送的消息,之后收到服务端的ack后,再从集合中删除消息,或者收到nack时,决定重新发送或是别的处理,总之,

发送方维护了消息集合,之后才有可能根据服务端返回deliveryTag,从集合中获得具体的消息。

如何使用呢?

首先,调用channel.confirmSelect将开启发送方确认:

channel.confirmSelect()

此后,信息被设置成confirm模式,发送方开始发送消息。

发送方有两种方式来处理服务端的响应:

  • 调用channel.waitForConfirms()等待服务端响应

    该调用会等待直到服务的响应,如果在该方法上次被调用之后,所以发送的消息都被服务端ack,则返回true,否则返回false。如果再次之前信道未被设置成confirm

    模式,那么waitForConfirms调用会抛出异常。使用waitForConfirms的示例如下:

    try {
    channel.confirmSelect();
    channel.basicPublish("cfmExchange","",null,"msg".getBytes());
    if(channel.waitForConfirms()) {
    System.out.println("send success");
    } else {
    System.out.println("send fail");
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  • 定义监听回调函数,处理服务端响应

    channel.addConfirmListener(new ConfirmListener() {
    public void handleAck(long deliveryTag, boolean multiple) throws IOException { } public void handleNack(long deliveryTag, boolean multiple) throws IOException { }
    });

    handleAck和handleNack分别处理被服务端ack和nack的消息;deliveryTag为消息编号,multiple设置为true是,一次性处理多条消息,即编号消息deliveryTag的消息。

RabbitMQ(5) 事务&生产者确认的更多相关文章

  1. rabbitmq 持久化 事务 发送确认模式

    部分内容来自:http://blog.csdn.net/hzw19920329/article/details/54315940 http://blog.csdn.net/hzw19920329/ar ...

  2. 【rabbitmq】rabbitmq概念解析--消息确认--示例程序

    概述 本示例程序全部来自rabbitmq官方示例程序,rabbitmq-demo: 官方共有6个demo,针对不同的语言(如 C#,Java,Spring-AMQP等),都有不同的示例程序: 本示例程 ...

  3. RabbitMQ (十二) 消息确认机制 - 发布者确认

    消费者确认解决的问题是确认消息是否被消费者"成功消费". 它有个前提条件,那就是生产者发布的消息已经"成功"发送出去了. 因此还需要一个机制来告诉生产者,你发送 ...

  4. springboot + rabbitmq 用了消息确认机制,感觉掉坑里了

    本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 最近部门号召大伙多组织一些技术分享会,说是要活跃公司的技术氛围,但早就看穿一切的我知道,这 T M 就是为了刷KPI ...

  5. rabbitmq监控之消息确认ack

    rabbitmq springboot ack 监控 一.测试环境 二.启动测试 一直以来,学习rabbitmq都是跟着各种各样的教程.博客.视频和文档,撸起袖子就是干!!!最后,也成功了. 当然,成 ...

  6. RabbitMQ:消息发送确认 与 消息接收确认(ACK)

    默认情况下如果一个 Message 被消费者所正确接收则会被从 Queue 中移除 如果一个 Queue 没被任何消费者订阅,那么这个 Queue 中的消息会被 Cache(缓存),当有消费者订阅时则 ...

  7. RabbitMQ五:生产者--队列--多消费者

    一.生成者-队列-多消费者(前言) 上篇文章,我们做了一个简单的Demo,一个生产者对应一个消费者,本篇文章就介绍 生产者-队列-多个消费者,下面简单示意图 P 生产者    C 消费者  中间队列 ...

  8. RabbitMQ - Publisher的消息确认机制

    queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consumer处理呢?毕竟对于 ...

  9. Kafka 幂等生产者和事务生产者特性(讨论基于 kafka-python | confluent-kafka 客户端)

    Kafka 提供了一个消息交付可靠性保障以及精确处理一次语义的实现.通常来说消息队列都提供多种消息语义保证 最多一次 (at most once): 消息可能会丢失,但绝不会被重复发送. 至少一次 ( ...

随机推荐

  1. 【AngularJS】通过jsonp与webmethod交互,实现ajax验证

    服务端配置 1:新建一个asp.net的网站 2: 创建一个服务文件:LoginService.asmx 注意:记得取消[System.Web.Script.Services.ScriptServic ...

  2. Linux使用free命令查看实际内存占用

    转自:http://www.cnblogs.com/pengdonglin137/p/3315124.html Linux下在终端环境下可以使用free命令看到系统实际使用内存的情况,一般用free ...

  3. Oracle中用sql语句取随机数和整数

    --- 应用round(5.678,3)保留小数 应用floor(5.678)保留整数 应用dbms_random.value(30,50)取得随机数 --- dbms_random包 获得随机小数S ...

  4. 谷歌技术"三宝"之MapReduce(转)

    原文地址:http://blog.csdn.net/opennaive/article/details/7514146 江湖传说永流传:谷歌技术有"三宝",GFS.MapReduc ...

  5. PHP 日期格式中 Y与y

    大写Y效果: $nowtime = time(); $nowtime=date("Y-m-d",$nowtime); 结果: 2015-10-24 小写y效果: $nowtime ...

  6. Python笔记 #01# Convert Python values into any type

    源:DataCamp datacamp 的 DAILY PRACTICE  + 日常收集. How much is your $100 worth after 7 years? Guess the t ...

  7. 写写Web API基础

    前两天突然心血来潮,对WEB Api 来了复习兴趣,虽然有很长时间没用了,现在有点迷湖.呀的!在VS2013的MVC项目(基于VS2012/MVC4的,如果是VS2013下的MVc5时,创建时勾上We ...

  8. zabbix分布式监控系统安装配置

    zabbix简介: zabbix(音同 zæbix)是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵 ...

  9. 机器学习:让我们彻底搞懂CNN【转】

    本文转载自:http://115.com/182920/T1266078.html 机器学习:让我们彻底搞懂CNN 上世纪科学家们发现了几个视觉神经特点,视神经具有局部感受眼,一整张图的识别由多个局部 ...

  10. [BZOJ2809]dispatching

    Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级. ...