幂等性为题

当我们在调用提交订单时  如果因为网络波动问题造成点击多次
调用方法或者接口不会改变业务状态  可以保证重复调用的结果和单次调用的结果一致


场景
 1前端重复提交
 2接口超时重试
 3消息队列重复消费

天然幂等性行为
  以sql语句为例
  select * from user where id=1 无论怎么查询 结果都为1 不变
  update user set age=18 where id=2
  delete from user where id=1
  insert into (user_id,username)values (1,'lcc') user_id 为主键自增
不具备幂等性
  update user set age=age+1 where id=1
  insert into(usr_id,username) value(1,'lcc') user_id不是主键 可以重复

解决方案
  1 token机制 第一次访问服务器时 服务器会响应浏览器一个token信息(并由该服务器将token 存储在--?redis中) 该浏览器携带token去访问另一个服务时携带该token 该服务会去reids中验证该token是否和redis中的token一致 若相同
  则删除该token
  若出现重复提交的话 会在redis中获取不到该token信息 解决的表单的重复提交
    

上述步骤1234 必须保证原子性
否则 当并发访问时 可能会在redis删除token之前
其他线程获取到token

 

 

基于token解决幂等性问题   解决防重提交

 

订单防重校验  通过lock加锁的方式来实现原子性操作

try {
            lock.lock();//加锁
            String redisToken = redisTemplate.opsForValue().get(key);
            if(redisToken!=null&& redisToken.equals(vo.getOrderToken())){
                //表示第一次提交
                //需要删除token
                redisTemplate.delete(redisToken);
            }else {
                //表示重复提交
                return responseVO;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();//释放锁
        }

我们还可以使用redis脚本来实现原子性处理

ublic OrderResponseVO submitOrder(OrderSubmit vo) {
        //表示需要返回的响应对象
        OrderResponseVO responseVO = new OrderResponseVO();
        //获取当前登陆的用户信息
        MemberVO memberVO = AuthInterceptor.threadLocal.get();
        //1 验证是否重复提交  保证redis中的token的查询和删除时一个原子性操作
        String key = OrderConstant.ORDER_TOKEN_PREFIX + ":" + memberVO.getId();
        //根据lua脚本
        String script="if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0";
        Long result = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class),
                Arrays.asList(key),
                vo.getOrderToken());
        if(result==0){
            //表示验证失败 说明是重复提交
            return responseVO;
        }
            //是第一次提交 令牌验证成功 开始下订单操作
            
       

 

 

  

 

posted @ 2022-06-15 21:35  花心大萝卜li  阅读(47)  评论(0)    收藏  举报