Spring Boot中幂等性的应用

Spring Boot 中,幂等性是实现分布式系统设计和接口调用的一个重要概念,尤其在高并发、分布式环境下,确保接口重复调用不会引发系统数据异常至关重要。

幂等性概念

幂等性(Idempotence)是指一次请求和重复多次请求对系统的影响完全相同。在接口调用中,如果一个接口满足幂等性,那么无论调用多少次,最终结果是一样的。

场景分析

  1. 支付系统
    防止重复支付。例如用户多次点击支付按钮,导致重复扣款。
  2. 订单创建
    防止用户重复下单,产生多个相同订单。
  3. 短信发送
    防止重复发送短信,避免浪费资源。
  4. 库存扣减
    防止并发扣减库存,导致库存不足或超卖。
  5. 分布式任务处理
    防止任务重复执行,保证最终一致性。

如何实现幂等性

在 Spring Boot 中,常用以下几种方法实现幂等性:

1.基于数据库唯一约束

原理:
利用数据库的唯一约束机制,确保同一请求只能操作一次。

实现:

  • 在数据库表中增加一个唯一字段(如订单号、请求 ID)。
  • 插入数据时,利用唯一约束防止重复写入。

代码示例:

@Entity
@Table(name = "orders", uniqueConstraints = {@UniqueConstraint(columnNames = "orderId")})
public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false)private String orderId; // 唯一订单号@Column(nullable = false)private BigDecimal amount;}

当重复提交时,数据库会抛出 DuplicateKeyException,可以捕获并返回提示。

2.基于唯一 Token 实现

原理:

  • 每次请求都需要携带唯一的 token,服务器校验 token 是否已使用。
  • 若已使用,则拒绝请求。

实现步骤:

1.客户端向服务器申请唯一 token(如 UUID)。

2.在请求时携带 token。

3.服务端验证 token:

  • 若 token 未使用,处理业务并标记 token 为已使用。
  • 若 token 已使用,直接返回提示。

代码示例:

@RestController
@RequestMapping("/api/order")
public class OrderController {@Autowiredprivate StringRedisTemplate redisTemplate;@PostMapping("/create")public String createOrder(@RequestParam String token) {// 校验 token 是否已存在Boolean isTokenExists = redisTemplate.opsForValue().setIfAbsent(token, "1", 10, TimeUnit.MINUTES);if (Boolean.FALSE.equals(isTokenExists)) {return "重复请求,请勿再次提交";}// 执行业务逻辑// ...return "订单创建成功";}}

优点:

  • 无需修改数据库结构。
  • 使用 Redis 提高性能,适用于高并发场景。

3.基于幂等字段校验

原理:

  • 接口请求体中包含幂等字段(如订单号、请求 ID)。
  • 服务端通过幂等字段判断请求是否已处理。

实现步骤:

  • 在业务表中增加 requestId 字段,标记唯一请求。
  • 每次请求前查询是否存在相同的 requestId。
  • 若存在,直接返回处理结果。

代码示例:

@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;public String createOrder(String requestId, Order order) {// 校验幂等字段if (orderRepository.existsByRequestId(requestId)) {return "订单已创建,请勿重复提交";}// 保存订单order.setRequestId(requestId);orderRepository.save(order);return "订单创建成功";}}

4.基于分布式锁

原理:

  • 利用分布式锁(如 Redis 的 SETNX)对关键资源加锁,确保同一时刻只有一个请求处理。

实现步骤:

  1. 请求时加锁,锁的唯一标识为幂等字段(如订单号)。
  2. 若加锁成功,执行业务逻辑。
  3. 业务执行完成后释放锁。

代码示例:

@Service
public class SmsService {@Autowiredprivate StringRedisTemplate redisTemplate;public String sendSms(String phoneNumber) {String lockKey = "sms:lock:" + phoneNumber;// 加锁Boolean isLockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 2, TimeUnit.MINUTES);if (Boolean.FALSE.equals(isLockAcquired)) {return "短信发送过于频繁,请稍后再试";}try {// 执行业务逻辑// ...return "短信发送成功";} finally {// 释放锁redisTemplate.delete(lockKey);}}}

5.基于状态校验

原理:

  • 根据业务状态判断请求是否重复。
  • 常用于支付、库存等有明确状态的场景。

实现步骤:

  • 增加状态字段(如订单状态、支付状态)。
  • 请求前校验状态是否已完成。

代码示例:

@Service
public class PaymentService {@Autowiredprivate OrderRepository orderRepository;public String payOrder(Long orderId) {Order order = orderRepository.findById(orderId).orElseThrow(() -> new RuntimeException("订单不存在"));// 校验状态if (order.getStatus().equals("PAID")) {return "订单已支付,请勿重复操作";}// 修改订单状态order.setStatus("PAID");orderRepository.save(order);return "支付成功";}}

幂等性设计注意事项

1.选择合适的幂等方案

  • 数据库唯一约束适合低并发场景。
  • Redis 分布式锁适合高并发场景。
  • 幂等字段校验适合需要记录请求 ID 的场景。

2.幂等字段的设计

  • 幂等字段应具有唯一性,如订单号、请求 ID。
  • 客户端生成或服务端分配均可。

3.幂等性与事务

  • 确保幂等校验与业务逻辑在同一事务中执行,避免校验通过但业务未执行完成的情况。

4.性能优化

  • 使用缓存(如 Redis)提高幂等校验性能,减少数据库压力。

总结

Spring Boot 中的幂等性实现,是确保接口安全性和数据一致性的关键。根据业务场景的不同,选择合适的幂等方案至关重要:

  • 数据库唯一约束:简单场景,直接使用。
  • Redis 分布式锁:高并发场景,提升性能。
  • 幂等字段校验:需要记录唯一请求的场景。

幂等性设计不仅是接口安全的保障,更是系统稳定性的核心体现。

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

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

相关文章

[项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结

目录 编写http_server模块 1. 引入cpp-httplib到项目中 2. cpp-httplib的使用介绍 3. 正式编写http_server 九、添加日志到项目中 十、编写前端模块 十一. 详解传 gitee 十二、项目总结 项目的扩展 写在前面 [项目详解][boost搜索引擎#1] 概述 | 去标签 | 数据清洗 |…

xxl-job 简单的入门到实战

本文是参考官方文档自己实践一次,纯享版,大致也是作者边写博客边去跟着官方文档实现 一、前期准备 1、官网地址 GitHub地址: GitHub - xuxueli/xxl-job: A distributed task scheduling framework.(分布式任务调度平台XXL-JOB&…

【教程】通过Docker运行AnythingLLM

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 官方教程:Local Docker Installation ~ AnythingLLM 1、先创建一个目录用于保存anythingllm的持久化文件: sudo mkdir /app su…

若依(RuoYi-Vue)+Flowable工作流前后端整合教程

此教程适合若依前后端分离项目,其他项目可以在扩展列表中进行查找。 近期公司里需要对很久以前的RuoYi-Vue前后端分离项目扩展出flowable的功能,当然这个重任也是落在了我的身上(不然也不会有这篇文章),然后我在官网看…

ubuntu 网络管理--NetworkManager

ubuntu 网络管理--NetworkManager 1 介绍2 NetworkManager 命令2 nmcli 命令显示可用的wifi AP连接wifi检查网络连接 ?? 如何删除删除网络连接查看设备状态添加一个新的以太网连接设置静态 IP 地址启用并测试连接添加新的wifi连接 3 其他命令参考 1 介绍 NetworkManager 是标…

水库大坝三维模型的开发和使用3Dmax篇

成果图 开发过程 工具插件three.js先加载模型做水体衔接水位测量标尺水位标记断面标记大坝监测点打点 上代码&#xff0c;技术交流V: bloxed <template><div class"box w100 h100"><el-row :gutter"20" v-loading"loading"e…

计算机毕设-基于springboot的校园招聘网站的设计与实现(附源码+lw+ppt+开题报告)

博主介绍&#xff1a;✌多个项目实战经验、多个大型网购商城开发经验、在某机构指导学员上千名、专注于本行业领域✌ 技术范围&#xff1a;Java实战项目、Python实战项目、微信小程序/安卓实战项目、爬虫大数据实战项目、Nodejs实战项目、PHP实战项目、.NET实战项目、Golang实战…

重生之我在异世界学编程之C语言:深入动态内存管理收尾 + 柔性数组篇

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文常见的动态内存管理错误&#xf…

无人直播源码

DY无人直播系统架构设计介绍 在DY等短视频平台的直播中&#xff0c;无人直播系统能够提供自动化、智能化的互动体验&#xff0c;既减轻了主播的工作量&#xff0c;又提升了观众的参与感。以下是一个典型的无人直播系统架构设计&#xff0c;包含全局配置、点对点互动、产品话术、…

被裁20240927 --- 嵌入式硬件开发 前篇

前篇主要介绍一些相关的概念&#xff0c;用于常识扫盲&#xff0c;后篇开始上干货&#xff01; 他捧着一只碗吃过百家的饭 1. 处理器芯片1.1 处理器芯片制造商一、 英特尔&#xff08;Intel&#xff09;二、 三星&#xff08;SAMSUNG&#xff09;三、 高通&#xff08;Qualcomm…

【Linux】进程间通信 -> 匿名管道命名管道

进程间通信的目的 数据传输&#xff1a;一个进程许需要将它的数据发送给另外一个进程。资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它们发生了某种事件&#xff08;如进程终止时要通知父进程…

Pytorch注意力机制应用到具体网络方法(闭眼都会版)

文章目录 以YoloV4-tiny为例要加入的注意力机制代码模型中插入注意力机制 以YoloV4-tiny为例 解释一下各个部分&#xff1a; 最左边这部分为主干提取网络&#xff0c;功能为特征提取中间这边部分为FPN&#xff0c;功能是加强特征提取最后一部分为yolo head&#xff0c;功能为获…

修改el-select下拉框高度;更新:支持动态修改

文章目录 效果动态修改&#xff1a;效果代码固定高度版本动态修改高度版本&#xff08;2024-12-25 更新&#xff1a; 支持动态修改下拉框高度&#xff09; 效果 动态修改&#xff1a;效果 代码 固定高度版本 注意点&#xff1a; popper-class 尽量独一无二&#xff0c;防止影…

如何完全剔除对Eureka的依赖,报错Cannot execute request on any known server

【现象】 程序运行报错如下&#xff1a; com.netflix.discovery.shared.transport.TransportException报错Cannot execute request on any known server 【解决方案】 &#xff08;1&#xff09;在Maven工程中的pom去掉Eureka相关的引用&#xff08;注释以下部分&#xff0…

vscode写python,遇到问题:ModuleNotFoundError: No module named ‘pillow‘(已解决 避坑)

1 问题&#xff1a; ModuleNotFoundError: No module named pillow 2 原因&#xff1a; 原因1&#xff1a;安装Pillow的pip命令所处的python版本与vscode调用的python解释器版本不同。 如&#xff1a; 原因2&#xff1a;虽然用的是pillow&#xff0c;但是写代码的时候只能用…

Ashy的考研游记

文章目录 摘要12.1112.2012.21 DAY1&#xff08;政治/英语&#xff09;政治英语 12.22 DAY2&#xff08;数学/专业课&#xff09;数学专业课 结束估分 摘要 在24年的12月里&#xff0c;Ashy完成了他的考研冲刺&#xff0c;顺利的结束了他本年度的考研之旅。 在十二月里&#…

AIGC实践|AI/AR助力文旅沉浸式互动体验探索

前言&#xff1a; 本篇文章的创作灵感来源于近期热门话题——让文物“动起来”&#xff0c;各大博物馆成为新进潮流打卡地。结合之前创作的AI文旅宣传片良好的流量和反馈&#xff0c;外加最近比较感兴趣的AR互动探索&#xff0c;想尝试看看自己能不能把这些零碎的内容整合起来…

Kubernetes(k8s)离线部署DolphinScheduler3.2.2

1.环境准备 1.1 集群规划 本次安装环境为&#xff1a;3台k8s现有的postgreSql数据库zookeeper服务 1.2 下载及介绍 DolphinScheduler-3.2.2官网&#xff1a;https://dolphinscheduler.apache.org/zh-cn/docs/3.2.2 官网安装文档&#xff1a;https://dolphinscheduler.apach…

C++的侵入式链表

非侵入式链表 非侵入式链表是一种链表数据结构&#xff0c;其中每个元素&#xff08;节点&#xff09;并不需要自己包含指向前后节点的指针。链表的结构和节点的存储是分开的&#xff0c;链表容器会单独管理这些指针。 常见的非侵入式链表节点可以由以下所示&#xff0c;即&a…

在vscode的ESP-IDF中使用自定义组件

以hello-world为例&#xff0c;演示步骤和注意事项 1、新建ESP-IDF项目 选择模板 从hello-world模板创建 2、打开项目 3、编译结果没错 正在执行任务: /home/azhu/.espressif/python_env/idf5.1_py3.10_env/bin/python /home/azhu/esp/v5.1/esp-idf/tools/idf_size.py /home…