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

前言:

正常情况下,消费者在消费消息后,会给消息队列发送一个确认,消息队列接收后就知道消息已经被成功消费了,然后就从队列中删除该消息,也就不会将该消息再发送给其他消费者了。不同消息队列发出的确认消息形式不同,RabbitMQ是通过发送一个ACK确认消息。但是因为网络故障,消费者发出的确认并没有传到消息队列,导致消息队列不知道该消息已经被消费,然后就再次消息发送给了其他消费者,从而造成重复消费的情况。

其实重复消费不可怕,可怕的是你没考虑到重复消费之后,怎么保证幂等性。假设你有个系统,消费一条往数据库里插入一条,要是你一个消息重复两次,不就插入了两条,这数据就错了。但是你要是消费到第二次的时候,自己判断一下已经消费过了,直接扔了,不就只保留了一条数据。

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

重复消费问题的解决思路是:保证消息的唯一性,即使多次传输,也不让消息的多次消费带来影响,也就是保证消息等幂性;幂等性指一个操作执行任意多次所产生的影响均与一次执行的影响相同

具体解决方案如下:
(1)改造业务逻辑,使得在重复消费时也不影响最终的结果。例如对SQL语句: update t1 set money = 150 where id = 1 and money = 100; 做了个前置条件判断,即 money = 100 的情况下才会做更新,更通用的是做个 version 即版本号控制,对比消息中的版本号和数据库中的版本号。

(2)基于数据库的的唯一主键进行约束。消费完消息之后,到数据库中做一个 insert 操作,如果出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。

(3)通过记录关键的key,当重复消息过来时,先判断下这个key是否已经被处理过了,如果没处理再进行下一步。. 生产者发送每条数据的时候,里面添加一个全局唯一的id, 消费者消费到消息后, 先根据消息id去redis中查询,如果redis不存在,就处理消息,然后将消息id写入redis。如果redis中存在,说明消息已经消费过,就不用处理。

① 通过数据库:比如处理订单时,记录订单ID,在消费前,去数据库中进行查询该记录是否存在,如果存在则直接返回。

② 使用全局唯一ID,再配合第三组主键做消费记录,比如使用 redis 的 set 结构,生产者发送消息时给消息分配一个全局ID,在每次消费者开始消费前,先去redis中查询有没有消费记录,如果消费过则不进行处理,如果没消费过,则进行处理,消费完之后,就将这个ID以k-v的形式存入redis中(过期时间根据具体情况设置)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/63646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

#Vue3篇:生命周期简洁

setup类似breforeCreate create setup() 钩子是在组件中使用组合式 API 的入口 挂载 onBeforeMount组件被挂载之前执行 onMounted 组件挂载完后执行 更新 onBeforeUpdate组件响应式状态变更而更新Dom树之后执行 onUpdated 组件响应式状态变更而更新Dom树之后执行 卸载 …

java 使用JSqlParser和CCJSqlParser 解析sql

maven <dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>4.9</version> </dependency>解析SQL String sql "select aa,bb from b"; Statement statementCCJSq…

动态规划——机器分配、01背包问题

一、机器分配 题目名称&#xff1a;机器分配 题目描述&#xff1a; 总公司拥有高效设备M台&#xff0c;准备分给下属的N个分公司。 各分公司若获得这些设备&#xff0c;可以为国家提供一定的盈利。 问&#xff1a;如何分配这M台设备才能使国家得到的盈利最大&#xff1f;求出最…

深入解析 JavaScript 中的 Blob 对象:二进制数据处理的核心

文章目录 1.Blob是什么2.Blob用法实例属性Blob方法slice方法text方法 示例1&#xff1a;字符串 Blob示例2&#xff1a;数组和字符串 Blob示例3&#xff1a;从文件输入创建 3.使用场景1.创建 Blob 并生成 URL&#xff0c;下载文件2.文件上传3.切片上传3.Blob用于URL在线预览PDF文…

NanoLog起步笔记-7-log解压过程初探

nonolog起步笔记-6-log解压过程初探 再看解压过程建立调试工程修改makefile添加新的launch项 注&#xff1a;重新学习nanolog的README.mdPost-Execution Log Decompressor 下面我们尝试了解&#xff0c;解压的过程&#xff0c;是如何得到文件头部的meta信息的。 再看解压过程 …

人工智能大模型LLM开源资源汇总(持续更新)

说明 目前是大范围整理阶段&#xff0c;所以存在大量机翻说明&#xff0c;后续会逐渐补充和完善资料&#xff0c;减少机翻并增加说明。 Github上的汇总资源&#xff08;大部分英文&#xff09; awesome-production-machine-learning 此存储库包含一系列精选的优秀开源库&am…

C++实现排序算法:冒泡排序

目录 前言 冒泡排序性质 C代码实现冒泡排序 冒泡图解 第一趟排序 第二趟排序 第三趟排序 排序结果 结语 前言 冒泡排序的基本思想是通过从前往后&#xff08;从后往前&#xff09;两两比较&#xff0c;若为逆序&#xff08;即arr[i] < arr[i 1]&#xff09;则交换…

中介者模式的理解和实践

一、中介者模式概述 中介者模式&#xff08;Mediator Pattern&#xff09;&#xff0c;也称为调解者模式或调停者模式&#xff0c;是一种行为设计模式。它的核心思想是通过引入一个中介者对象来封装一系列对象之间的交互&#xff0c;使得这些对象不必直接相互作用&#xff0c;从…

PlantUML——类图

背景 类图是UML模型中的静态视图&#xff0c;其主要作用包括&#xff1a; 描述系统的结构化设计&#xff0c;显示出类、接口以及它们之间的静态结构和关系。简化对系统的理解&#xff0c;是系统分析与设计阶段的重要产物&#xff0c;也是系统编码和测试的重要模型依据。 在U…

【Java知识】Java进阶-如何开启远程调式

java远程调试 概述Java远程调试的开启与底层原理开启Java远程调试底层原理 JVM参数 概述 Java远程调试的开启与底层原理 开启Java远程调试 Java远程调试允许开发者在本地IDE&#xff08;如Eclipse、IntelliJ IDEA等&#xff09;中调试运行在远程服务器上的Java应用程序。以下…

入选国家数据局案例!浙江“一体化智能化公共数据平台”总体架构详解~

国家数据局在2024中国国际大数据产业博览会上发布了首批50个数字中国建设典型案例。案例涉及数据基础设施、数据资源、数字技术创新、数字政府、数字经济、数字社会、数字文化、数字生态文明等领域&#xff0c;集中反映了近年来数字中国建设的实践和成效。 其中&#xff0c;由…

vscode IntelliSense Configurations

IntelliSense 是一个强大的代码补全和代码分析功能&#xff0c;它可以帮助开发者提高编程效率。图中显示的是 VSCode 的 IntelliSense 配置界面&#xff0c;具体配置如下&#xff1a; Compiler path&#xff08;编译器路径&#xff09;: 这里指定了用于构建项目的编译器的完整路…

同三维TL200H2S6 6机位精品教育录播主机

录制点播、直播导播、互动、音频处理器、中控等多功能为一体 8路视频输入:6路SDI1路HDMI1(4K30)1路(3选1:HDMI2/2路VGA) 2路视频输出&#xff1a;1路HDMI1(4K30)1路&#…

欢乐斗地主案例

1&#xff0c;创建对象 package anlidoudizhu;public class pai implements Comparable<pai> {private Double value;private String name;Overridepublic int compareTo(pai o) {return -Double.compare(this.value,o.value);}//升序排序&#xff0c;treeset集合public…

技术型企业如何高效搭建企业博客以增强品牌影响力和市场竞争力

在数字化时代&#xff0c;技术型企业面临着激烈的市场竞争和快速变化的行业环境。为了在这场竞争中脱颖而出&#xff0c;企业需要寻找新的营销渠道和品牌建设工具。企业博客作为一种低成本、高效率的在线内容平台&#xff0c;已经成为技术型企业增强品牌影响力和市场竞争力的重…

go-zero(十二)消息队列

go zero 消息队列 在微服务架构中&#xff0c;消息队列主要通过异步通信实现服务间的解耦&#xff0c;使得各个服务可以独立发展和扩展。 go-zero中使用的队列组件go-queue&#xff0c;是gozero官方实现的基于Kafka和Beanstalkd 的消息队列框架,我们使用kafka作为演示。 一、…

【JAVA高级篇教学】第二篇:使用 Redisson 实现高效限流机制

在高并发系统中&#xff0c;限流是一项非常重要的技术手段&#xff0c;用于保护后端服务&#xff0c;防止因流量过大导致系统崩溃。本文将详细介绍如何使用 Redisson 提供的 RRateLimiter 实现分布式限流&#xff0c;以及其原理、使用场景和完整代码示例。 目录 一、什么是限流…

基于卷积神经网络的Caser算法

将一段交互序列嵌入到一个以时间为纵轴的平面空间中形成“一张图”后&#xff0c;基于卷积序列嵌入的推荐&#xff08;Caser&#xff09;算法利用多个不同大小的卷积滤波器&#xff0c;来捕捉序列中物品间的点级&#xff08;point-level&#xff09;、联合的&#xff08;union-…

ubuntu下的chattts 学习5:Example: self introduction

代码 import ChatTTS import torch import torchaudiochat ChatTTS.Chat() chat.load(compileFalse) # Set to True for better performance ################################### inputs_en """ chat T T S is a text to speech model designed for dialogu…

【银河麒麟高级服务器操作系统】修改容器中journal服务日志存储位置无效—分析及解决方案

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 【机型】 整机类型/架构&am…