Pulsar 也会重复消费?

背景
许久没有分享 Java 相关的问题排查了,最近帮同事一起排查了一个问题:
在使用
Pulsar消费时,发生了同一条消息反复消费的情况。
排查
当他告诉我这个现象的时候我就持怀疑态度,根据之前使用的经验 Pulsar 在官方文档以及 API 中都解释过:


只有当设置了消费的 ackTimeout 并超时消费时才会重复投递消息,默认情况下是关闭的,查看代码也确实没有开启。
那会不会是调用了 negativeAcknowledge() 方法呢(调用该方法也会触发重新投递),因为我们使了一个第三方库 https://github.com/majusko/pulsar-java-spring-boot-starter 只有当抛出异常时才会调用该方法。
查阅代码之后也没有地方抛出异常,甚至整个过程中都没看到异常产生;这就有点诡异了。
复现
为了捋清楚整个事情的来龙去脉,详细了解了他的使用流程;
其实也就是业务出现了 bug,他在消息消费时 debug 然后进行单步调试,当走完一次调试后,没多久马上又收到了同样的消息。
但奇怪的是也不是每次 debug 后都能重复消费,我们都说如果一个 bug 能 100% 完全复现,那基本上就解决一大半了。
所以我们排查的第一步就是完全复现这个问题。
为了排除掉是 IDEA 的问题(虽然极大概率不太可能)既然是 debug 的时候产生的问题,那其实转换到代码也就是 sleep 嘛,所以我们打算在消费逻辑里直接 sleep 一段时间看能否复现。
经过测试,sleep 几秒到几十秒都无法复现,最后索性 sleep 一分钟,神奇的事情发生了,每次都成功复现!
既然能成功复现那就好说了,因为我自己的业务代码也有使用到 Pulsar 的地方,为了方便调试就准备在自己的项目里再复现一次。
结果诡异的事情再次发生,我这里又不能复现了。
虽然这才是符合预期的,但这就没法调了呀。
本着相信现代科学的前提,我们俩唯一的区别就是项目不一样了,为此我对比了两边的代码。
@PulsarConsumer(
topic = xx,
clazz = Xx.class,
subscriptionType = SubscriptionType.Shared
)
public void consume(Data msg) {
log.info("consume msg:{}", msg.getOrderId());
Lock lock = redisLockRegistry.obtain(msg.getOrderId());
if (lock.tryLock()) {
try {
orderService.do(msg.getOrderId());
} catch (Exception e) {
log.error("consumer msg:{} err:", msg.toString(), e);
} finally {
lock.unlock();
}
}
}
结果不出所料,同事那边的代码加了锁;一个基于 Redis 的分布式锁,这时我一拍大腿不会是解锁的时候超时了导致抛了异常吧。
为了验证这个问题,在能复现的基础上我在框架的 Pulsar 消费处打了断点:


果然破案了,异常提示已经非常清楚了:加锁已经过了超时时间。
进入异常后直接 negative 消息,同时异常也被吃掉了,所以之前没有发现。

查阅了 RedisLockRegistry 的源码,默认超时时间正好是一分钟,所以之前我们 sleep 几十秒也无法复现这个问题。
总结
事后我向同事了解了下为啥这里要加锁,因为我看下来完全没有加锁的必要;结果他是因为从别人那里复制的代码才加上的,压根没想那么多。
所以这事也能得出一些教训:
- ctrl C/V 虽然方便,但也得充分考虑自己的业务场景。
- 使用一些第三方 API 时,需要充分了解其作用、参数。
你的点赞与分享是对我最大的支持
Pulsar 也会重复消费?的更多相关文章
- Kafka重复消费和丢失数据研究
Kafka重复消费原因 底层根本原因:已经消费了数据,但是offset没提交. 原因1:强行kill线程,导致消费后的数据,offset没有提交. 原因2:设置offset为自动提交,关闭kafka时 ...
- Kafka消息保证不丢失和重复消费问题
使用同步模式的时候,有3种状态保证消息被安全生产,在配置为1(只保证写入leader成功)的话,如果刚好leader partition挂了,数据就会丢失.还有一种情况可能会丢失消息,就是使用异步模式 ...
- Spring Cloud Stream如何处理消息重复消费?
最近收到好几个类似的问题:使用Spring Cloud Stream操作RabbitMQ或Kafka的时候,出现消息重复消费的问题.通过沟通与排查下来主要还是用户对消费组的认识不够.其实,在之前的博文 ...
- kafka consumer重复消费问题
在做分布式编译的时候,每一个worker都有一个consumer,适用的kafka+zookeep的配置都是默认的配置,在消息比较少的情况下,每一个consumer都能均匀得到互不相同的消息,但是当消 ...
- kafka丢失和重复消费数据
Kafka作为当下流行的高并发消息中间件,大量用于数据采集,实时处理等场景,我们在享受他的高并发,高可靠时,还是不得不面对可能存在的问题,最常见的就是丢包,重发问题. 1.丢包问题:消息推送服务,每天 ...
- 程序重启RocketMQ消息重复消费
最近在调试RocketMQ消息发送与消费的Demo时,发现一个问题:只要重启程序,RocketMQ消息就会重复消费. 那么这是什么原因导致的,又该如何解决呢? 经过一番排查,发现程序使用的Rocket ...
- 【消息队列】kafka是如何保证消息不被重复消费的
一.kafka自带的消费机制 kafka有个offset的概念,当每个消息被写进去后,都有一个offset,代表他的序号,然后consumer消费该数据之后,隔一段时间,会把自己消费过的消息的offs ...
- r-mq实现顺序消费,不重复消费
根据订单号,同一订单号的消息,会被发送到同一个topic下的同一个queue,发送端的有序,会导致topic中消息的有序,而consumer和queue是一对多?的关系.可以保证topic中的有顺序的 ...
- kafka一直rebalance故障,重复消费
今天我司线上kafka消息代理出现错误日志,异常rebalance,而且平均间隔2到3分钟就会rebalance一次,分析日志发现比较严重.错误日志如下 08-09 11:01:11 131 pool ...
随机推荐
- 手把手教你实现pynq-z2条形码识别
我是 雪天鱼,一名FPGA爱好者,研究方向是FPGA架构探索和SOC设计. 关注公众号,拉你进"IC设计交流群". 1.前言 单单实现一个二维码识别就花了将近一个星期,这篇文章我就 ...
- 有手就行10——Jenkins+SonarQube代码审查
有手就行10--Jenkins+SonarQube代码审查 Jenkins+SonarQube代码审查(1) - 安装SonarQube Jenkins+SonarQube代码审查(2) - 实现代码 ...
- MySQL数据库初识、下载使用(针对库、表、记录的增删改查)
今日内容概要 数据演变史 数据库软件的本质 MySQL简介 下载与安装 基本配置 基本SQL语句 内容详细 1.数据演变史 # 1.单独的文本文件 没有固定的存放位置和格式 文件名:user.txt ...
- Solution -「ARC 101E」「AT 4352」Ribbons on Tree
\(\mathcal{Description}\) Link. 给定一棵 \(n\) 个点的树,其中 \(2|n\),你需要把这些点两两配对,并把每对点间的路径染色.求使得所有边被染色的方案数 ...
- Python+selenium自动循环扔QQ邮箱漂流瓶
Python代码如下: # coding=utf-8 from selenium import webdriver from time import sleep from random import ...
- JSP中引入JQuery和Layer,浏览器控制台报错404
路径没有写错,文件也存在为什么会报404呢?,解决方法是将layer文件夹使用source的方式 解决办法: 这时候你会发现layer文件夹变成了蓝色,重启一次服务器,页面中就没有报404异常了 总结 ...
- java连接到sql sever 2008_java基础学习
(sql sever 2008跟sql sever 2005装载JDBC驱动的方法是一样的) 一.加载驱动的文字教程 1.准备相关的软件(Eclipse除外,开源软件可以从官网下载) <1> ...
- 思迈特软件Smartbi发展再提速,完成B+轮过亿战略融资
2021年4月,思迈特软件(Smartbi)宣布完成亿级B+轮战略融资,本轮投资方为领先的全球企业级数据分析和组织智能服务平台提供商--明略科技.此前,思迈特软件曾先后获得来自价值资本.方广资本的数千 ...
- 60天shell脚本计划-4/12-渐入佳境
--作者:飞翔的小胖猪 --创建时间:2021年2月11日 --修改时间:2021年2月15日 说明 每日上传更新一个shell脚本,周期为60天.如有需求的读者可根据自己实际情况选用合适的脚本,也可 ...
- linux 解决磁盘占用100%
df -h 查看磁盘使用情况 ll -h 查看文件的大小 使用如下命令查找大于100M的大文件,发现有几个日志文件及临时文件比较大,使用rm –rf删除即可. find / -size +10 ...