如何做到接口幂等性

防止接口多次提交 保证幂等性

什么情况需要幂等性

数据库
  • 查询 天然幂等性
  • 更新 sql更新无论发生多少次 数据库都是1
  • 删除 无论删除多少次 第一次删除成功后 就已经没有相应的id 对应无法删除
  • 插入 插入都是主键唯一 不重复的 幂等性

  • 更新库存 如果不断加库存 那么这个就不是幂等性的更新
  • 插入 不带主键唯一 就不是幂等性

token机制做到幂等性

  • 自己的思考
    类似验证码 既然是幂等性 肯定需要Redis来限制次数 并且要与客户端浏览器有关系
    分布式集群下 用共享的redis来存储 当前这个客户端的浏览器token
    redis K-V: token–uuidCookie
    只要是这个用户请求的这个接口如果redis 里当前这个接口的标记还没有删除 就要返回幂等性
if(redis.get("token")=null){
  返回幂等性
}
redis.put("token","uuid");
等到真个业务流程跑完了 redis.delete(); 就做到幂等了吧
  • 老师的答案在这里插入图片描述
    两个点不同
    1.老师的服务器提前存储token 即设计的时候就指定前端工程师让客户点击这个接口的按钮会在请求头中加入这个token 我以为浏览器会自带token 其实我想错了 因为接口幂等性 浏览器自带的token是当前这台电脑 这个人的身份维度的 而接口的token这个细维度 浏览器是无法提供的 需要前端自己设计
    在这里插入图片描述

2.我是执行完任务再删除 他是判断完就删除 都是因为第一点思考不全面导致后面的做法不同
如果一开始就已经redis里存值 势必要做到第一次请求过来 匹配成了redis删除就代表已经有过来的请求了
而且要在匹配完就删除 而不是业务执行完就删除 因为匹配完没删除 又有第二个请求过来又匹配成了 就创建了两个请求 没有幂等
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在分布式服务中 从redis里获取令牌 并且对比令牌 的时候 可能第二个请求已经进来 并且两个请求同时删除令牌 彼此都没有被redis.getToken() 是否为空 这个条件防御住 就这样创建了两个请求 没有保证幂等
所以获取对比删除这三点必须要保证原子性 直到完成删除 别的请求才能进来

场景实现 电商订单幂等性

1.做到服务器提前存储token
用户点击提交订单 服务器这边会创建订单 为了做到订单幂等性 不重复创建 根据上面分析 我们要提前在服务器中存储当前提交订单接口的token 那在什么时候 存储呢 这个业务线是如何穿起来的呢

在展示订单接口时候 就将提交订单的token存储到服务器

在这里插入图片描述
在这里插入图片描述

 @GetMapping("//")
    public  void  showOrder(@RequestBody Vo vo){
       String token=UUID.randomUUID().toString().replace("-","");
       redisTemplate.opsForValue().set("接口token",token );
       vo.setToken(token);
   }

在这里插入图片描述
在展示页面接口取出来的token 放到提交订单接口按钮的前端携带体里
在这里插入图片描述

提交订单验证原子令牌 保证幂等性

https://blog.csdn.net/wts563540/article/details/109994948

无法通过 原子性

 String redisToken = redisTemplate.opsForValue().get(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberResponseVO.getId());
        if (orderToken != null && orderToken.equals(redisToken)){
           //令牌验证通过
          redisTemplate.delete(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberResponseVO.getId());
        }else {
            //不通过
       }


在这里插入图片描述
前面的数组是Redis存的值 后面的数组是要确认的值
在本需求中 前面的就是

 Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberResponseVO.getId()), orderToken);

保证了客户端提交订单 服务器创建订单的原子性 服务器redis对比 如果已经有了请求标志 那就返回客户端提示

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值