文档章节

如何保证消息不被重复消费

五彩的颜色
 五彩的颜色
发布于 11/20 10:03
字数 1209
阅读 36
收藏 0

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

如何保证消息不被重复消费?(如何保证消息消费的幂等性)

举个例子吧。假设你有个系统,消费一条消息就往数据库里插入一条数据,要是你一个消息重复两次,你不就插入了两条,这数据不就错了?但是你要是消费到第二次的时候,自己判断一下是否已经消费过了,若是就直接扔了,这样不就保留了一条数据,从而保证了数据的正确性。

一条数据重复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性。

幂等性,通俗点说,就一个数据,或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错。

所以第二个问题来了,怎么保证消息队列消费的幂等性?

其实还是得结合业务来思考,我这里给几个思路:

  • 比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update 一下好吧。

  • 比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。

  • 比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据这个 id 去比如 Redis 里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个 id 写 Redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。

  • 比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。

剖析

首先,比如 RabbitMQ、RocketMQ、Kafka,都有可能会出现消息重复消费的问题,正常。因为这问题通常不是 MQ 自己保证的,是由我们开发来保证的。挑一个 Kafka 来举个例子,说说怎么重复消费吧。

Kafka 实际上有个 offset 的概念,就是每个消息写进去,都有一个 offset代表消息的序号,然后 consumer 消费了数据之后,每隔一段时间(定时定期),会把自己消费过的消息的 offset 提交一下,表示“我已经消费过了,下次我要是重启啥的,你就让我继续从上次消费到的 offset 来继续消费吧”。

但是凡事总有意外,比如我们之前生产经常遇到的,就是你有时候重启系统,看你怎么重启了,如果碰到点着急的,直接 kill 进程了,再重启。这会导致 consumer 有些消息处理了,但是没来得及提交 offset,尴尬了。重启之后,少数消息会再次消费一次。

举个栗子。

有这么个场景。数据 1/2/3 依次进入 kafka,kafka 会给这三条数据每条分配一个 offset,代表这条数据的序号,我们就假设分配的 offset 依次是 152/153/154。消费者从 kafka 去消费的时候,也是按照这个顺序去消费。假如当消费者消费了 offset=153 的这条数据,刚准备去提交 offset 到 zookeeper,此时消费者进程被重启了。那么此时消费过的数据 1/2 的 offset 并没有提交,kafka 也就不知道你已经消费了 offset=153 这条数据。那么重启之后,消费者会找 kafka 说,嘿,哥儿们,你给我接着把上次我消费到的那个地方后面的数据继续给我传递过来。由于之前的 offset 没有提交成功,那么数据 1/2 会再次传过来,如果此时消费者没有去重的话,那么就会导致重复消费。

如果消费者干的事儿是拿一条数据就往数据库里写一条,会导致说,你可能就把数据 1/2 在数据库里插入了 2 次,那么数据就错啦。 如感觉文章对你有所帮助,可以关注微信公众号【五彩的颜色】鼓励一下

© 著作权归作者所有

五彩的颜色
粉丝 0
博文 45
码字总数 34031
作品 0
天津
私信 提问
RocketMQ原理(4)——消息ACK机制及消费进度管理

https://zhuanlan.zhihu.com/p/25140744 中剖析过,consumer的每个实例是靠队列分配来决定如何消费消息的。那么消费进度具体是如何管理的,又是如何保证消息成功消费的(RocketMQ有保证消息肯...

xiaomin0322
2018/04/14
298
0
springboot + rabbitmq发送邮件(保证消息100%投递成功并被消费)

前言: RabbitMQ相关知识请参考: https://www.jianshu.com/p/cc3d2017e7b3 Linux安装RabbitMQ请参考: https://www.jianshu.com/p/ee9f7594212b Windows安装RabbitMQ请参考: https://www.jians......

wangzaiplus
07/19
0
0
阿里消息中间件ONS消息乱序问题(二)

顺序消息:消息的有序是 消息消费时,能够按照发送的顺序进行消费。 例如:假如生产者产生的两条消息M1 、M2 要保证两条消息的顺序来消费应该怎么做,我们可能想到这样的场景: M1发送到S1 ...

哲别0
2018/03/26
63
0
kafka学习(8)如何保证数据有序,处理数据丢失和数据重复消费

首先了解一下kafka消息生产者和消费者是如何处理消息的 生产者发送消息有两种方式,同步(sync)和异步 (async) Kafka 消息发送分同步 (sync)、异步 (async) 两种方式,默认使用同步方式,可通...

太猪-YJ
04/09
97
0
阿里消息中间件ONS消息重复问题和事物问题(三)

产生的原因:网络不可达问题。 网络超时之后我们可以做的只有两件事,1 停止(回滚,但对于系统来说影响特别大) 2 继续(另发送到别的服务消费端) 一般我们采用第二种处理方式,但是要经过...

哲别0
2018/03/26
157
0

没有更多内容

加载失败,请刷新页面

加载更多

阿里巴巴的 Kubernetes 应用管理实践经验与教训

作者 | 孙健波(天元) 阿里巴巴技术专家 导读:本文整理自孙健波在 ArchSummit 大会 2019 北京站演讲稿记录。首先介绍了阿里巴巴基于 Kubernetes 项目进行大规模应用实践过程中遇到的问题;...

阿里巴巴云原生
29分钟前
4
0
pinpoint采样原理分析

使用pinpoint进行全链路监控时,支持对请求的采样,某条请求是否被采样,取决于整个链路开始的机器。该机器使用特定的采样算法。采样的标志会一直在链路中透传。比如在http里面,会在header里...

xiaomin0322
34分钟前
4
0
在IDEA开发工具中使用lombok

1. 首先我们需要安装IntelliJ IDEA中的lombok插件,打开IntelliJ IDEA后点击菜单栏中的File-->Settings,或者使用快捷键Ctrl+Alt+S进入到设置页面 我们点击设置中的Plugins进行插件的安装,在...

欧阳飘
35分钟前
5
0
爱码仕 5G生活畅想 (五) 每个人每个家庭都有一朵私有的云

30年前,微软让每个家庭都有一台电脑的理念成为了现实;而今云计算的观念已为老百姓们所熟识。数据就是能源;数据就是财富;谁生产了数据,这数据的所有权就归谁所有。随着原生云基础设施的完...

LitStone
37分钟前
4
0
嵌入式入门:嵌入式领域的职业发展方向是什么?

嵌入式入门:嵌入式领域的职业发展方向是什么? 在如今的IT市场上看,嵌入式的发展的应用都是广受欢迎的,在嵌入式入门学习中,我们可以发现嵌入式的发展方向有很多,门槛高低不一样。下面就...

xyd118
37分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部