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

幂等性简单介绍

1. 幂等性是什么

  • 核心定义:操作重复执行多次的最终效果与执行一次的效果完全相同
  • 通俗理解:无论调用多少次,结果都像只调用一次,不会因多次调用产生额外副作用。
  • 关键点
    • 关注最终状态而非过程
    • 强调重复执行的安全性
    • 是分布式系统、网络通信、数据库操作的重要特性

2. 需要防止幂等性问题的场景

常见诱因

  • 用户重复点击/刷新页面
  • 网络超时触发重试
  • 消息队列重复消费
  • 微服务调用重试
  • 恶意攻击(如重复支付)
  • 定时任务重复触发

导致的后果

  • 重复下单(多次扣款单次发货)
  • 重复扣款/发放优惠券
  • 数据状态混乱(如库存负数)
  • 业务逻辑错误

3. 需要幂等性的场景

天然幂等的操作(无需额外设计)
操作类型示例说明
查询 (Read)SELECT * FROM orders WHERE id=123;多次查询返回相同结果
纯删除 (Delete)DELETE FROM users WHERE id=456;首次删除后后续操作无影响
设值更新 (Update)UPDATE product SET price=99 WHERE id=1;最终状态固定为设定值
完整替换 (PUT)PUT /user/123 {完整数据}多次替换结果相同
需设计幂等性的操作
  • 创建操作INSERT INTO orders...(会生成重复数据)
  • 条件更新UPDATE account SET balance=balance-100...(多次执行多扣款)
  • 状态转换:订单状态从 UNPAIDPAID(需防重复支付)
  • 部分更新PATCH /user {points:+10}(多次执行累加积分)
  • 外部调用:支付接口、短信通知等有副作用的操作

4. 幂等性实现方案(以用户重复下单为例)

方案1:Token 机制
1. 用户进入下单页 → 服务端生成Token存Redis并返回前端
2. 首次提交:携带Token → 服务端验证Token存在 → 执行业务 → 删除Token
3. 重复提交:携带相同Token → 服务端检查Token不存在 → 拒绝操作

特点:防止前段重复提交,需要配合Redis

方案2:唯一索引
ALTER TABLE orders ADD UNIQUE INDEX (order_no); -- 订单号唯一约束
首次提交:INSERT订单成功(订单号=SN20250723001)
重复提交:INSERT相同订单号 → 触发唯一约束异常 → 拦截重复订单

特点:数据库层面强校验,适合创建操作

方案3:乐观锁(版本号)
-- 订单表结构
id | status   | version
------------------------
123 | UNPAID  | 1-- 支付操作SQL
UPDATE orders 
SET status='PAID', version=version+1 
WHERE id=123 AND version=1 AND status='UNPAID';
首次支付:版本号1匹配 → 更新成功(version→2)
重复支付:版本号1不匹配(当前version=2)→ 更新0行 → 判定为重复请求

特点:适合更新操作,需维护版本字段

方案4:状态机控制
定义状态流:UNPAID → PAID → SHIPPED
首次支付:UNPAID→PAID(允许)
重复支付:PAID→PAID(禁止状态跃迁)→ 拒绝操作

很多时候,业务流程是有状态流转的,这个时候可以使用状态机来保证幂等性。

如订单业务中,存在状态「1-已下单,2-已支付,3-已完成,4-已取消」,按照业务流程,状态是依次流转的,所以在update操作时,我们就要根据本次的状态来更新下一次的状态。

状态机其实是乐观锁的一种特例。

 update order_info set status = 3 where id = 123 and status = 2;

特点:业务逻辑自约束,适合状态转换场景(乐观锁的一种实现方式)

方案5:分布式锁
  • 锁可以解决幂等性问题,但是一般不用(性能较低)
1. 生成锁Key:lock:order:user_001
2. 首次请求:获取Redis锁成功 → 创建订单 → 释放锁
3. 重复请求:获取相同Key锁失败 → 直接返回"操作频繁"

特点:强一致性,但性能开销大

http://www.dtcms.com/a/294188.html

相关文章:

  • 网络与信息安全有哪些岗位:(2)渗透测试工程师
  • 耐达讯自动化EtherCAT转RS232:示波器连接的“开挂秘籍”
  • 在mac 上zsh 如何安装最新的 go 工具
  • CGA老年人能力评估师:提升老年生活质量
  • SOLIDWORKS2025教育版集成了电气与自动化设计功能
  • iOS上使用WebRTC推拉流的案例
  • RabbitMQ有多少种Exchange?
  • 微软2025教育AI报告:教育群体采用AI的比例显著提升
  • 【lucene】实现knn
  • Vue TodoList案例
  • Task 01 学习笔记
  • 若依前后端分离版学习笔记(二)——系统菜单介绍
  • 在写作软件中画地图,Canvas 绘图在地图设计中应用
  • 音视频学习(四十三):H264无损压缩
  • 基于CEEMDAN+SSA-TCN-BiLSTM-Attention的混合预测模型
  • 汽车电子架构
  • UE5 如何显示蓝图运行流程
  • MySQL进阶学习与初阶复习第一天
  • 音视频中一些常见的知识点
  • OpenCV(01)基本图像操作、绘制,读取视频
  • 枚举右,维护左
  • 【音视频学习】四、深入解析视频技术中的YUV数据存储方式:从原理到实践
  • Web3 开发者进阶学习图谱
  • 面向对象分析与设计40讲(7)设计原则之合成复用原则
  • 用 PyTorch 实现全连接网络识别 MNIST 手写数字
  • 【Unity编辑器开发与拓展Handles】
  • PyTorch中nn.Module详解和综合代码示例
  • 不同地区的主要搜索引擎工具
  • Java项目中定时任务三方工具和技术的深度应用指南
  • C#定时任务实战指南:从基础Timer到Hangfire高级应用