多次请求与修改的并发控制:多实例下分布式锁和乐观锁的应用

2023-12-16 12:29:38

前提:
在正式环境中,由于存在多个实例,同一笔订单可能会被多次请求到我的数据汇总接口。为了避免重复处理订单,我采用了分布式锁来进行拦截。

另外,考虑到在 1 秒内可能会有多笔不同订单同时进行数据修改,如果直接修改可能会出现数据覆盖的情况。例如,订单 A 的金额是 1 元,订单 B 的金额是 2 元,如果不采取任何措施直接修改,汇总表中的金额可能会出现 1 元、2 元或 3 元的情况,而不是正确的 4 元。为了解决这个问题,我们采用了乐观锁来限制并发修改,以确保数据的准确性。

以下是处理代码

			//分布式锁
 			String lockKey = "profit_export_log"+orderNo;
            // true-加锁成功
            boolean isSuccess = RedisUtils.getRedisStringTemplate().opsForValue().setIfAbsent(lockKey,orderNo, Constant.TEN, TimeUnit.MINUTES);
            if (!isSuccess) {
                log.info("汇总分润-{}. id:{}. lockKey:{}. 获取分布式锁失败!", "汇总分润" ,orderNo, lockKey);
                return;
            }
   	   //乐观锁
       MiddleCollectVo collectVo = MiddleCollectMapper.queryOneValue(exportLogMiddleVo);
       MiddleCollectDto collectDto = BeanMapperUtils.map(exportLogMiddleVo, MiddleCollectDto.class);
        updateNoRefundCgcProfitExportLogCollect(exportLogMiddleVo, collectVo, collectDto);
        int newVersion = collectVo.getVersion() + 1;
        MiddleCollect value = BeanMapperUtils.map(collectDto,MiddleCollect.class);
        LambdaUpdateWrapper<MiddleCollect> wrapper= Wrappers.lambdaUpdate(MiddleCollect.class);
        wrapper.eq(MiddleCollect::getId, collectVo.getId());
        wrapper.eq(MiddleCollect::getVersion, collectVo.getVersion());
        value.setVersion(newVersion);
        boolean judge = this.update(value, wrapper);
        if(!judge) {
            updateAgain(exportLogMiddleVo);
        }

文章来源:https://blog.csdn.net/weixin_47287824/article/details/135030234
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。