第十三章 RabbitMQ之消息幂等性

server/2024/10/18 22:11:26/

目录

一、引言

二、消息幂等解决方案

2.1. 方案一

2.2. 方案二


一、引言

幂等是一个数学概念,用函数表达式来描述是这样的:f(x) = f(f(x)) 。在程序开发中,则是指同一个业务,执行一次或多次对业务状态的影响是一致的。有些业务天生就是幂等的,如查询和删除业务执行一次和多次的结果是一样的,而像用户下单、用户退款是非幂等业务。

实际项目开发中,我们在提交表单时,很多时候可能会重复提交表单,这个时候我们通过token令牌等唯一标识来解决,第一次提交页面将缓存中的唯一标识删除,后面再重新提交时缓存中的标识已经被删了因此重复提交失败。

我们在消息消费的过程中也会存在同样的问题,即如何来保障所有业务在接收RabbitMQ消息时保证业务的幂等性,避免消息重复消费呢?

二、消息幂等解决方案

2.1. 方案一

1. 给每个消息都设置/生成一个唯一id,利用id区分是否是重复消息,与消息一起投递给消费者。

2. 消费者接收到消息后处理自己的业务,业务处理成功后将消息ID保存到数据库

3. 如果下次又收到相同消息,去数据库查询判断是否存在,存在则为重复消息放弃处理

 核心代码:

我们可以在生产者和消费者两端分别声明消息转换器的Bean,本案例为了方便直接在启动类中声明消息转换器,并配置自动为消息创建id。

package com.example.consumer;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}@Beanpublic MessageConverter messageConverter(){// 1.定义消息转换器Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();// 配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息jjmc.setCreateMessageIds(true);return jjmc;}
}
package com.example.publisher;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;@SpringBootApplication
public class PublisherApplication {public static void main(String[] args) {SpringApplication.run(PublisherApplication.class, args);}@Beanpublic MessageConverter messageConverter(){// 1.定义消息转换器Jackson2JsonMessageConverter jjmc = new Jackson2JsonMessageConverter();// 配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息jjmc.setCreateMessageIds(true);return jjmc;}
}

通过源码可以看到默认生成的是UUID:

 通过RabbitMQ浏览器界面可以看到消息已经生成了一个唯一ID :

2.2. 方案二

结合业务逻辑,基于业务本身做判断。以余额支付业务为例,我们要在支付后修改订单状态为已支付,应该在修改订单状态前先查询订单状态,判断状态是否是未支付。只有未支付订单才需要修改,其他状态不做处理:

核心代码 

 上述代码可以通过乐观锁来实现,替换代码如下:

 


http://www.ppmy.cn/server/132871.html

相关文章

内网dbeaver连接OceanBase4.2.2数据库及问题处理

本文记录了内网dbeaver如何配置连接到OceanBase4.2.2数据库及问题处理。 如何安装dbeaver请参见本人文章:数据库可视化管理工具dbeaver试用及问题处理 一、系统环境 1、终端系统 2、dbeaver版本 版本: 23.0.2.202304091457绿色版,23.3.5等新版也是可…

vue3学习:数字时钟遇到的两个问题

在前端开发学习中,用JavaScript脚本写个数字时钟是很常见的案例,也没什么难度。今天有时间,于是就用Vue的方式来实现这个功能。原本以为是件非常容易的事,没想到却卡在两个问题上,一个问题通过别人的博文已经找到答案&…

kubernetes(k8s)面试之2024

1、什么是k8s? K8s是kubernetes的简称,其本质是一个开源的容器编排系统,主要用于管理容器化的应用, 简单点就是k8s是一个编排容器的系统,一个可以管理容器应用全生命周期的工具,从创建应用,应用…

GC1277替代OCH477/灿瑞芯片在电脑散热风扇中的应用

随着科技的不断进步,电脑硬件的性能不断提升,随之而来的散热需求也日益增加。为了有效地管理散热,散热风扇的控制芯片扮演着至关重要的角色。本文将探讨芯麦的GC1277芯片如何替代OCH477/灿瑞芯片,应用于电脑散热风扇中。 一、背景…

x86-64 能兼容 i386 的系统吗

是的,x86-64(也称为AMD64或x64)架构可以兼容i386(也称为IA-32)系统。x86-64是x86架构的64位扩展,它向后兼容16位及32位的x86架构。这意味着你可以在x86-64架构的虚拟机上运行i386系统。 兼容性 硬件兼容性…

VBA技术资料MF210:按顺序号复制工作表中的图片

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…

python项目实战——下载美女图片

python项目实战——下载美女图片 文章目录 python项目实战——下载美女图片完整代码思路整理实现过程使用xpath语法找图片的链接检查链接是否正确下载图片创建文件夹获取一组图片的链接获取页数 获取目录页的链接 完善代码注意事项 完整代码 import requests import re import…

连锁店收银系统源码+电子发票

​ 传统纸质开票模式,流程复杂、时间长,为解决商户开票难的问题,千呼新零售2.0上线了电子发票功能,开通方便,使用简便!商户只需要简单配置,就可以实现门店实现开票自由! 一、线下订…