rabbitmq 重复确认导致消息丢失

背景

rabbitmq 在应用场景中,大多采用工作队列 work-queue的模式。

在一个常见的工作队列模式中,消费者 worker 将不断的轮询从队列中拉取最新消息,当队列负载压力增大时允许添加多个worker 进行处理。
然而执行一个任务可能需要相当的时长,这是由业务特性所决定的;如果 worker执行任务过程中出现异常甚至宕机,此时消息便会丢失,这是简单消息队列难以解决的问题。

rabbitmq 采用了消息确认机制来防止此类问题,在该机制中,worker需要向 MQ Server 返回 ACK响应以表示消息已确认处理;
在以下情况下,rabbitmq 会对消息进行重新投递:
1 client 未响应ACK, 主动关闭 Channel;
2 client 未响应ACk, 网络异常断开;

消息的重发机制没有超时限制,只要client 不响应ACK,那么会一直投递;
如果启用了消息持久化机制,那么消息将有进一步的保障。

问题描述及分析

1 客户端为简化应答处理,可以设置自动应答选项,如:

  boolean autoAck = false;
channel.basicConsume(TASK_QUEUE_NAME, autoAck, consumer);

2 如果不启用自动应答,需要应用代码手动进行应答:

    try {
doWork(message);
} finally {
logger.info(" xxx work done");
channel.basicAck(envelope.getDeliveryTag(), false);
}

3 当两种方案同时存在

由于客户端的编码失误,先启用了自动应答选项,又在应用代码执行了应答的代码:
     // enable autoAck
boolean autoAck = true;
consumerChannel.basicConsume(queueName, autoAck, this); //... // snipper from Consumer.handleDelivery method
// send ack to server
try {
consumerChannel.basicAck(deliveryTag, true);
} catch (Exception e) {
}

多了一次确认,应用代码貌似一切如常。 但在频繁进行消息收发测试时发现 消息存在随机性丢失处理的情况!
检查 rabbitmq server日志发现以下异常:

  {amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}
...
{amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}
...
{amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}
...

提示未知的 delivery tag=1,该字段为MQ server 用于消息确认的标记,服务端因无法识别而打印错误。
另外一个现象则是,连续收发消息 5次,其中丢失消息处理1次,而 rabbitmq server错误日志出现 4次!

经过分析,发现问题原因所在:
rabbitmq 为每一个channel维护了一个delivery tag的计数器,这里采用正向自增,新消息投递时自增,当消息响应时自减;
在连续收发的场景中,由于消息发送的间隔较短,部分消息因 consumer的重复确认被rabbitmq 当做已处理而丢弃。

解决方案

取消consumer 的自动应答机制,仅保留手动应答的处理,问题解决。

参考资料

关于 rabbitmq 消息确认机制:
http://www.rabbitmq.com/confirms.html#when

rabbitmq 重复ACK导致消息丢失的更多相关文章

  1. APNS导致消息丢失和发送效率原因

    http://blog.csdn.net/tlq1988/article/details/9612237 首先说明一下,本文只是介绍一些容易被开发者忽视,而导致性能低下问题.并不是介绍如何向苹果设备成 ...

  2. 解决RabbitMQ消息丢失问题和保证消息可靠性(一)

    原文链接(作者一个人):https://juejin.im/post/5d468591f265da03b810427e 工作中经常用到消息中间件来解决系统间的解耦问题或者高并发消峰问题,但是消息的可靠 ...

  3. RabbitMQ防止消息丢失

    转载请注明出处 0.目录 RabbitMQ-从基础到实战(1)— Hello RabbitMQ RabbitMQ-从基础到实战(3)— 消息的交换 1.简介 RabbitMQ中,消息丢失可以简单的分为 ...

  4. 如何处理RabbitMQ 消息堆积和消息丢失问题

    消息堆积 解决方案: 增加消费者或后台相关组件的吞吐能力 增加消费的多线程处理 根据不同的业务实现不同的丢弃任务,选择不同的策略淘汰任务 默认情况下,RabbitMQ消费者为单线程串行消费,设置并行消 ...

  5. RabbitMQ 和 Kafka 的消息可靠性对比

    RabbitMQ和Kafka都提供持久的消息保证.两者都提供至少一次和至多一次的保证,另外,Kafka在某些限定情况下可以提供精确的一次(exactly-once)保证. 让我们首先理解一下上述术语的 ...

  6. RabbitMQ-从基础到实战(2)— 防止消息丢失

    转载请注明出处 1.简介 RabbitMQ中,消息丢失可以简单的分为两种:客户端丢失和服务端丢失.针对这两种消息丢失,RabbitMQ都给出了相应的解决方案. 2.防止客户端丢失消息 如图,生产者P向 ...

  7. RabbitMQ实战:理解消息通信

    RabbitMQ是一个开源的消息代理和队列服务器,可以通过基本协议在完全不同的应用之间共享数据,可以将作业排队以便让分布式服务进行处理. 本篇介绍下消息通信,首先介绍基础概念,将这些概念映射到AMQP ...

  8. 【RabbitMQ】如何进行消息可靠投递【上篇】

    说明 前几天,突然发生线上报警,钉钉连发了好几条消息,一看是RabbitMQ相关的消息,心头一紧,难道翻车了? [橙色报警] 应用[xxx]在[08-15 16:36:04]发生[错误日志异常],al ...

  9. RocketMQ消息丢失解决方案:同步刷盘+手动提交

    前言 之前我们一起了解了使用RocketMQ事务消息解决生产者发送消息时消息丢失的问题,但使用了事务消息后消息就一定不会丢失了吗,肯定是不能保证的. 因为虽然我们解决了生产者发送消息时候的消息丢失问题 ...

随机推荐

  1. MVC之路随记2--Razor基础

    1.概述:Razor是mvc 3.0新扩展的内容,是默认的视图引擎,引擎一词可理解为Web Form中<% %>中的变形,但是Razor更加干净,轻量级,简单.使用了该引擎后,文件的后缀名 ...

  2. Windows7+VS2010下OpenGL的环境配置

    http://johnhany.net/2014/01/environment-for-opengl-with-vs2010/ OpenGL(Open Graphics Library)是一个开放的. ...

  3. ajax请求!

    ajax请求: var data ='{"useName":"'+name+'",}' $.ajax({ type:"post", url: ...

  4. google vr开源 cardboard

    https://developers.google.com/cardboard/android/ 待续

  5. Ajax学习心得

    Ajax学习心得 大致学了下Ajax,才知道它不是某种编程语言,而是一种在无需加载整个页面的情况下能够更新部分网页的技术.了解了它的功能后觉得这真是一种好的技术,这得给前端和运维省多少力啊! 传统的网 ...

  6. python 字符串内建函数

    方法 描述 string.capitalize() 把字符串的第一个字符大写 string.center(width) 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 string ...

  7. BackTrack5-r3任务栏显示网络图标及自定义DNS

    任务栏显示网络连接图标:安装NM工具,在BT终端中执行:apt-get install network-manager按y继续执行,显示:ldconfig deferred processing no ...

  8. codeforces 721C (拓排 + DP)

    题目链接:http://codeforces.com/contest/721/problem/C 题意:从1走到n,问在时间T内最多经过多少个点,按路径顺序输出. 思路:比赛的时候只想到拓排然后就不知 ...

  9. Maven项目pom.xml文件详解

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  10. IOS UI多线程 NSThread 下载并显示图片到UIImageView

    效果图 @property (weak,nonatomic)IBOutletUILabel *downLabelInfo; @property (weak,nonatomic)IBOutletUIIm ...