接口的幂等性

今天在做一个需求的时候,要求考虑接口的幂等性,后台根据模板生成pdf时,要求只能生成一次,后续请求都只能是查询到生成的pdf。

为什么会出现重复请求?

  • 网络波动:内部调用会存在重试机制,dubbo接口默认有重试机制,服务的restful接口也有重试机制,axios也有重试机制。
  • 用户重复点击:用户点击过快
  • 浏览器:回退操作等都可能导致重复请求

在网络不稳定、客户端重试、用户重复提交等场景下,同一个请求可能被多次发送到服务端。如果没有幂等性保障,可能导致:

  • 重复下单
  • 重复扣款
  • 数据重复插入
  • 状态错误变更

从前端的角度去考虑幂等性

  • 如果是按钮,防止用户点击过快,可以在用户点击后就进入loading状态,不可再使用
  • 如果是表单,提交后跳转,且不允许后退重新提交表单

从后端角度考虑幂等性:能够正确识别出相同的请求,并且合理处理非首次到达的请求。

  • Token机制:

    用户在进入到提交的页面时,自动从后台获取token,然后提交时携带token,然后保证token只能校验一次 Redis实现:进入页面颁发token,发生请求时删除token,删除成功则放行。

    ini 复制代码
    String script = """
        if redis.call('EXISTS', KEYS[1]) == 1 then
            redis.call('DEL', KEYS[1])
            return 1
        else
            return 0
        end
    """;
    ​
    RedisScript<Long> redisScript = RedisScript.of(script, Long.class);
    Long result = redisTemplate.execute(redisScript, Collections.singletonList("my_token"));
    ​
    if (result == 1) {
       // Token 存在并已删除,可以执行业务
    } else {
        // Token 不存在,处理重复请求
    }

    某些场景,可以考虑将这个token交由客户端生成,能够保证客户端安全可控即可,可以直接用现成的setnx命令。

  • 数据库唯一约束:通过接口的请求中一些能够唯一标识请求的数据作为key存放到数据库中 如提前生成订单号,在下单时再真正插入订单数据,用订单号作为数据库的主键。

  • 乐观锁:默认获取锁,执行完逻辑,真正保存数据时再校验是否能成功获取到锁。

    如:update的时候用当前订单状态(初始状态)作为条件。

  • 悲观锁:用redis实现分布式锁,先获取锁再执行逻辑,执行完逻辑后再释放锁。

  • 状态机: 如订单场景:进入通过set status = process where status=initial and order_id=xx,如果update影响条数为1则表明修改状态成功能执行对应逻辑,否则拒绝执行。

相关推荐
止语Lab40 分钟前
好的 DX 不等于少写代码——三种语言的摩擦力设计课
后端
吃饱了得干活40 分钟前
别再手动解析 LLM 输出了!LangChain 四种结构化输出方案对比
后端·python·langchain
程序员天天困1 小时前
Arthas trace 命令怎么用?一行定位最慢那行代码
jvm·后端
Huiturn1 小时前
GPT 5.6 连续编码 10 小时,纯 Python 啃下 Word 二进制格式——doc2docx 实现拆解
后端
用户298698530141 小时前
Python 实现 Excel 与 Markdown 互转的实用指南
后端·python·excel
用户77283104908401 小时前
krono-job:零侵入、单二进制交付的分布式任务调度平台(开源)
后端
Conan在掘金1 小时前
鸿蒙报错速查:Function lacks ending return statement,返回路径漏 return 就炸,根因 + 真解法
后端
人间凡尔赛1 小时前
AI-Native 云原生架构:2026 年从容器编排到智能体编排的范式革命
后端·云原生·架构
IT_陈寒2 小时前
Vue的响应式让我加班到凌晨3点,原来问题出在这
前端·人工智能·后端
卷无止境2 小时前
提升 Python 代码健壮性的方法大盘点
后端·python