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

第十三章 RabbitMQ之消息幂等性

目录

一、引言

二、消息幂等解决方案

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.lryc.cn/news/458096.html

相关文章:

  • tpcms-master.zip
  • Spring国际化和Validation
  • ②EtherCAT转ModbusTCP, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关
  • 【华为HCIP实战课程八】OSPF网络类型及报文类型详解,网络工程师
  • 信息安全工程师(28)机房安全分析与防护
  • 大数据处理从零开始————9.MapReduce编程实践之信息过滤之学生成绩统计demo
  • 自动化测试 | 窗口截图
  • 初中数学网上考试系统的设计与实现(论文+源码)_kaic
  • 关系运算(3)
  • tp6的系统是如何上架的
  • Vue:开发小技巧
  • 力扣之1369.获取最近第二次的活动
  • Python 和 Jupyter Kernel 版本不一致
  • Android常用布局
  • 初级网络工程师之从入门到入狱(五)
  • JavaScript轮播图实现
  • 【LLM开源项目】LLMs-开发框架-Langchain-Tutorials-Basics-v2.0
  • Python 爬取天气预报并进行可视化分析
  • 最左侧冗余覆盖子串
  • 性能测试-JMeter(2)
  • 芯课堂 | Synwit_UI_Creator(μgui)平台之图像处理篇
  • QT C++ 软键盘/悬浮键盘/触摸屏键盘的制作
  • element-ui点击文字查看图片预览功能
  • SpringBoot集成Redis使用Cache缓存
  • 【瑞萨RA8D1 CPK开发板】lcd显示
  • 算法收敛的一些证明方法与案例
  • 基于vue框架的蛋糕店网上商城740g7(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
  • 你真的了解Canvas吗--解密六【ZRender篇】
  • 孤独相伴 - 结婚十七年
  • json-server,跨域