关于幂等问题

面试时面试官老是爱问这个东西,特此记录一下。

什么是幂等?

幂等:多次调用方法和接口时,可以保证重复调用和单次调用的结果是一样的。

使用幂等的场景有哪些?

  1. 前端重复提交
  2. 接口请求失败时的重试
  3. 消息重复消费

接口请求方面问题解决

  1. 前端解决方案
    前端防重 (不可靠)
    前端提交后跳转(较常见的用法,简称prg)

  2. 后端解决方案
    token(redis),需要前端配合,且并发情况下需要使用分布式锁保证原子性
    这和登录验证token类似,只不过这个token是一次性的。
    在实际接口请求之前,前端访问服务器接受token(全局唯一,一般使用流水号),前端携带token请求服务器,后端验证该token是否存在于redis,存在则执行并删除redis中的token,不存在则直接返回。

  3. redis-SETNX(分布式锁)
    和token类似,不过逻辑相反,如果setnx存入key值失败,则表示已存在对应key,说明是重复提交,反之不是。考虑到并发,可以使用lua表达式注销查询和删除方法。
    ``
    /**
    * 创建 Token 存入 Redis,并返回该 Token
    * @param value 用于辅助验证的 value 值
    * @return 生成的 Token 串
    */
    public String generateToken(String value) {

    String token = UUID.randomUUID().toString();
    String key = IDEMPOTENT_TOKEN_PREFIX + token;
    /**

    • 在真实业务中 采用唯一标志 例如 流水号啊
      */
      redisTemplate.opsForValue().set(key, value, 5, TimeUnit.MINUTES);
      return token;
      }
/**
 * 分布式锁实现幂等性
 */
@PostMapping("/distributeLock")
@ApiOperation(value = "分布式锁实现幂等性")
public String distributeLock(HttpServletRequest request) {

    String token = request.getHeader("token");
    // 获取用户信息(这里使用模拟数据)
    String userInfo = "mydlq";
    RLock lock = redissonClient.getLock(token);
    lock.lock(10, TimeUnit.SECONDS);
    try {

       Boolean flag = tokenUtilService.validToken2(token, userInfo);
        // 根据验证结果响应不同信息
        if (flag) {

            /**
             * 执行正常的逻辑
             */
            log.info("执行正常的逻辑………………");
        }
        return flag ? "正常调用" : "重复调用";
    } catch (Exception e) {

        e.printStackTrace();
        return  "重复调用";
    } finally {

        lock.unlock();
    }
}

``asd

服务层面问题

  1. 防重表
    字面意思,建一张数据库表,多个字段作为唯一主键,每次向数据表插入数据之前,先向防重表中插入数据,如果重复则表示是重复数据。
  2. mysql 乐观锁(基于版本号和基于条件)
  3. zookeeper分布式锁

rabbitmq重复消息问题

  1. 重复发送:发送前,从redis获取消息唯一标识,如果已存在,则不发送,如果不存在则发送并设置唯一标识
  2. 重复处理:消费前,根据消息的唯一标识查询,如果已存在于数据库或redis,则丢弃,否则消费并确认
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值