当前位置: 首页 > news >正文

【RabbitMQ业务幂等设计】RabbitMQ消息是幂等的吗?

在分布式系统中,RabbitMQ 自身不直接提供消息幂等性保障机制,但可通过业务逻辑设计和技术组合实现消息处理的幂等性。以下是 8 种核心实现方案及最佳实践:


一、消息唯一标识符 (Message Deduplication)

  1. 原理

    • 每条消息携带全局唯一ID(如 UUID、Snowflake ID)
    • 消费者维护已处理消息ID的存储(Redis/DB)
  2. 实现步骤

    // 生产者端
    MessageProperties props = new MessageProperties();
    props.setMessageId(UUID.randomUUID().toString());
    Message message = new Message(body.getBytes(), props);// 消费者端
    @RabbitListener(queues = "order_queue")
    public void process(Message message) {String msgId = message.getMessageProperties().getMessageId();if (redis.setnx(msgId, "processed") == 1) {// 处理业务逻辑// 成功后设置过期时间防止存储膨胀redis.expire(msgId, 72 * 3600); } else {// 幂等拦截}
    }
    

二、版本号控制 (Optimistic Concurrency Control)

  1. 适用场景
    数据更新类操作(如账户余额修改)

  2. 实现方案

    -- 消息体包含数据版本号
    UPDATE account 
    SET balance = new_balance, version = version + 1 
    WHERE id = 123 AND version = current_version;
    

三、状态机驱动 (State Machine)

  1. 应用场景
    订单状态流转(创建→支付→发货)

  2. 实现示例

    public void handleOrderMessage(OrderMessage msg) {Order order = orderDao.get(msg.getOrderId());if (order.getStatus() != msg.getExpectedStatus()) {log.warn("状态不匹配,当前状态:{}", order.getStatus());return;}// 执行状态变更逻辑
    }
    

四、业务唯一键约束

  1. 实现方式
    CREATE TABLE payment_records (id BIGINT PRIMARY KEY,order_no VARCHAR(64) UNIQUE, -- 业务唯一键amount DECIMAL(10,2)
    );-- 插入时捕获唯一键冲突
    try {insertPaymentRecord();
    } catch (DuplicateKeyException e) {// 幂等处理
    }
    

五、消息确认策略优化

  1. 关键配置

    spring:rabbitmq:listener:simple:acknowledge-mode: manual  # 手动ACKretry:enabled: truemax-attempts: 3         # 最大重试次数
    
  2. 处理逻辑

    @RabbitListener(queues = "critical_queue")
    public void process(Message message, Channel channel) throws IOException {try {// 业务处理channel.basicAck(tag, false);} catch (Exception e) {channel.basicNack(tag, false, false); // 直接进入死信队列}
    }
    

六、分布式锁机制

  1. Redis 分布式锁示例
    public void processWithLock(Message msg) {String lockKey = "msg_lock:" + msg.getId();try {if (redisLock.tryLock(lockKey, 30)) {// 真正的业务处理}} finally {redisLock.unlock(lockKey);}
    }
    

七、时序控制 (Timestamp Validation)

  1. 实现逻辑
    if (message.getEventTime() < lastProcessedTime.get()) {log.info("丢弃过期消息,事件时间:{}", message.getEventTime());return;
    }
    

八、消息轨迹追踪表

  1. 设计表结构

    CREATE TABLE message_log (message_id VARCHAR(64) PRIMARY KEY,status ENUM('PROCESSING','SUCCESS','FAILED'),processed_time DATETIME,retry_count INT DEFAULT 0
    );
    
  2. 处理流程

    // 开启事务
    beginTransaction();
    try {// 1. 插入消息记录insertMessageLog(msgId, "PROCESSING");// 2. 执行业务操作processBusinessLogic();// 3. 更新状态updateMessageStatus(msgId, "SUCCESS");commit();
    } catch (Exception e) {rollback();
    }
    

最佳实践组合建议

  1. 金融交易场景
    唯一ID + 版本号控制 + 数据库唯一约束 + 分布式锁

  2. 电商订单场景
    状态机 + 业务唯一键 + 消息轨迹表

  3. 日志处理场景
    时序验证 + Redis去重 + 自动重试策略


注意事项

  1. 存储选择权衡

    • Redis: 高性能但存在数据丢失风险
    • 数据库: 可靠性高但性能较低
    • 建议:关键业务使用DB+缓存双写
  2. 清理策略

    • 设置合理的TTL(例如72小时)
    • 定时任务清理已处理记录
  3. 性能优化

    • 使用Bloom Filter减少内存消耗
    • 批量查询优化(如一次查询1000个ID是否存在)

通过以上方案组合,可在不同业务场景中实现可靠的幂等处理,建议根据实际业务压力和数据一致性要求选择合适的实现层级。

相关文章:

【RabbitMQ业务幂等设计】RabbitMQ消息是幂等的吗?

在分布式系统中&#xff0c;RabbitMQ 自身不直接提供消息幂等性保障机制&#xff0c;但可通过业务逻辑设计和技术组合实现消息处理的幂等性。以下是 8 种核心实现方案及最佳实践&#xff1a; 一、消息唯一标识符 (Message Deduplication) 原理 每条消息携带全局唯一ID&#xff…...

flutter在安卓模拟器上运行

目录 下载android studio&#xff0c;然后把其中的模拟器设为环境变量&#xff0c;然后在vscode/cursor中使用插件&#xff0c;打开安卓模拟器一、下载android studio网址mac 下载64位 ARM 二、启动android studio三、设置SDK四、打开文件 打开模拟器五、运行程序六、在vscode/…...

linux shell 当命令执行出现错误立即退出的方法

在 Linux 脚本中&#xff0c;如果你想在整个脚本执行完毕后检查是否有错误发生&#xff0c;可以通过以下几种方式实现&#xff1a; 1. 使用 $? 检查上一条命令的退出状态 每个命令执行后&#xff0c;Shell 会将其退出状态存储在特殊变量 $? 中。$? 的值为 0 表示成功&#…...

与本地电脑PDF文档对话的PDF问答程序

文章目录 PDF问答程序程序流程处理PDF文档创建问答链 在探索和学习新技术时&#xff0c;了解LangChain框架的理论知识固然重要&#xff0c;但实际的案例分析与实践尝试能为你提供更加直观的认识和更深人的理解。本文主要以解析案例代码为主。通过具体的实践操作&#xff0c;你可…...

QT之改变鼠标样式

QT改变鼠标图片 资源路径如下 代码实现 QPixmap customCursorPixmap(":/images/mouse.png");QCursor customCursor(customCursorPixmap);QWidget::setCursor(customCursor); // 可以设置为整个窗口或特定控件QWidget::setCursor(); // 设置为透明光标&#xff0c…...

后端开发:开启技术世界的新大门

在互联网的广阔天地中&#xff0c;后端开发宛如一座大厦的基石&#xff0c;虽不直接与用户 “面对面” 交流&#xff0c;却默默地支撑着整个互联网产品的稳定运行。它是服务器端编程的核心领域&#xff0c;负责处理数据、执行业务逻辑以及与数据库和其他后端服务进行交互。在当…...

Sun-Panel:简洁且美观的导航首页开源项目!!

在这个数字化飞速发展的时代&#xff0c;我们几乎每个人都拥有自己的服务器或者NAS。但问题来了&#xff0c;管理这些设备往往需要记住一大堆复杂的命令和界面&#xff0c;对于像了不起这样追求简洁生活的程序员来说&#xff0c;简直是噩梦&#xff01; 今天介绍一款界面清爽&…...

第4章 信息系统架构(四)

4.6 网络架构 网络是信息技术架构中的基础&#xff0c;不仅是用户请求和获取IT信息资源服务的通道&#xff0c;同时也是 信息系统架构中各类资源融合和调度的枢纽。特别是云计算、大数据和移动互联网技术飞速发 展的今天&#xff0c;网络更加成为实现这些技术跨越的重要环节。…...

【Java八股文】07-Redis面试篇

【Java八股文】07-Redis面试篇 Redis面试篇认识redis为什么用 Redis 作为 MySQL 的缓存&#xff1f; 数据结构讲一下Redis底层的数据结构ZSet底层是由什么实现的 线程模型Redis 是单线程吗&#xff1f;Redis怎么进行I/O多路复用的&#xff1f;Redis 采用单线程为什么还这么快&a…...

Windows PyCharm的python项目移动存储位置后需要做的变更

项目使用的venv虚拟环境&#xff0c;因此项目移动存储位置后需要重新配置python解释器的位置&#xff0c;否则无法识别&#xff0c;若非虚拟环境中运行&#xff0c;则直接移动后打开即可&#xff0c;无需任何配置。 PyCharm版本为2021.3.3 (Professional Edition)&#xff0c;其…...

微信小程序消息推送解密

package com.test.main.b2b;import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Arrays;/*** author * version 1.0* description: 解谜微信小…...

《道德经的现代智慧:解码生活与商业的底层逻辑2》

第二章&#xff1a;人际互动的智慧 &#x1f91d; 引言&#xff1a;现代人际关系的困境 &#x1f31f; 时代背景&#xff1a;超连接时代的人际迷思 &#x1f310; 在这个前所未有的超连接时代&#xff0c;我们似乎比任何时候都更"在线"、更"联系"&#…...

通过监督微调提升多语言大语言模型性能

引言 澳鹏助力一家全球科技公司提升其大语言模型&#xff08;LLM&#xff09;的性能。通过提供结构化的人工反馈形式的大语言模型训练数据&#xff0c;让该模型在30多种语言、70多种方言中的表现得到优化。众包人员们进行多轮对话&#xff0c;并依据回复的相关性、连贯性、准确…...

用deepseek学大模型05逻辑回归

deepseek.com:逻辑回归的目标函数&#xff0c;损失函数&#xff0c;梯度下降 标量和矩阵形式的数学推导&#xff0c;pytorch真实能跑的代码案例以及模型,数据&#xff0c;预测结果的可视化展示&#xff0c; 模型应用场景和优缺点&#xff0c;及如何改进解决及改进方法数据推导。…...

图解循环神经网络(RNN)

目录 1.循环神经网络介绍 2.网络结构 3.结构分类 4.模型工作原理 5.模型工作示例 6.总结 1.循环神经网络介绍 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种专门用于处理序列数据的神经网络结构。与传统的神经网络不同&#xff0c…...

vue文件没有name属性怎么被调用

如果你在 index.vue 文件中定义了一个组件&#xff0c;但没有在组件定义中使用 name 属性&#xff0c;你仍然可以通过几种方式来引用和使用这个组件。 1. 使用局部注册 在父组件中直接导入并注册 index.vue 中的组件&#xff08;index.vue没有name属性&#xff09;&#xff0…...

YOLOv11-ultralytics-8.3.67部分代码阅读笔记-build.py

build.py ultralytics\data\build.py 目录 build.py 1.所需的库和模块 2.class InfiniteDataLoader(dataloader.DataLoader): 3.class _RepeatSampler: 4.def seed_worker(worker_id): 5.def build_yolo_dataset(cfg, img_path, batch, data, mode"train"…...

alt+tab切换导致linux桌面卡死的急救方案

环境 debian12 gnome43.9 解决办法 观察状态栏&#xff0c;其实系统是没有完全死机的&#xff0c;而且gnome也可能没有完全死机。 1. alt f4 关闭桌面上的程序&#xff0c;因为这个方案是我刚刚看到的&#xff0c;所以不确定能不能用&#xff0c;比起重启系统&#xff0c;…...

Spark(2)linux和简单命令

&#xff08;一&#xff09;Linux的文件系统 文件系统&#xff1a;操作系统中负责管理和存储文件信息的软件结构称为文件管理系统。 文件系统的结构通常叫做目录树结构&#xff0c;从斜杆/根目录开始; Linux号称万物皆文件&#xff0c;意味着针对Linux的操作&#xff0c;大多…...

如何在Windows下使用Ollama本地部署DeepSeek R1

参考链接&#xff1a; 通过Ollama本地部署DeepSeek R1以及简单使用的教程&#xff08;超详细&#xff09; 【DeepSeek应用】DeepSeek R1 本地部署&#xff08;OllamaDockerOpenWebUI&#xff09; 如何将 Chatbox 连接到远程 Ollama 服务&#xff1a;逐步指南 首先需要安装oll…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...