接口的幂等性

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

相关推荐
干翻秋招5 小时前
Java知识点复习
后端·面试
Postkarte不想说话5 小时前
Cisco配置BGP
后端
小帅说java5 小时前
【Java开发】Java热门框架深入开发第11篇:学习目标,一、SpringBoot简介【附代码文档】
javascript·后端
CodeSheep5 小时前
JetBrains官宣,又一个IDE可以免费用了!
前端·后端·程序员
间彧6 小时前
SpringBoot和Servlet的联系
后端
间彧6 小时前
Spring Boot的DispatcherServlet是如何封装和扩展原生Servlet功能的?
后端
无名之辈J6 小时前
GC Overhead 的排查
后端
道19936 小时前
50 台小型无人车与50套穿戴终端 5 公里范围内通信组网方案深度研究
java·后端·struts
间彧6 小时前
Spring Boot中,拦截器和Spring AOP有什么区别
后端