接口的幂等性

今天在做一个需求的时候,要求考虑接口的幂等性,后台根据模板生成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则表明修改状态成功能执行对应逻辑,否则拒绝执行。

相关推荐
zhangxingchao1 小时前
多 Agent 架构到底怎么选?从 Claude Agent Teams、Cognition/Devin 到工程落地原则
前端·人工智能·后端
IT_陈寒2 小时前
SpringBoot那个自动配置的坑,害我排查到凌晨三点
前端·人工智能·后端
ServBay2 小时前
OpenCode 和它的7款必备插件
后端·github·ai编程
ping某2 小时前
逐字节拆解 tcpdump
后端
阿凡9807302 小时前
花 100 dollar,用 Claude 打通 EasyEDA&Fusion 双向同步
后端·程序员
irving同学462382 小时前
从零搭建生产级 RAG:Embedding、Chunking、Hybrid Search 与 Reranker
前端·后端
她的男孩2 小时前
从零搭一个企业后台,为什么我把能力拆成 Starter 和 Plugin
java·后端·架构
胡志辉2 小时前
本地 AI 编码助手从 0 配起来:先选模型,再接 Ollama、VS Code、Claude Code 和 Codex
前端·后端
RainCity2 小时前
Java Swing 自定义组件库分享(七)
java·笔记·后端
啷里格啷2 小时前
第二章 Fast-DDS 整体架构与分层框架
后端·架构