【解决案例】分布式锁Redission加锁无效

案例背景
项目需求是生成一段自增的编号,由于编号涵盖不同字符,所以需要编写生成编号的逻辑

1. 问题初解决,加锁

在有该需求前提下,编写如下伪代码

@Transaction(rollbackFor = Exception.class)
    public void test() {
        //获取当前数据库编号信息并做一定处理得到生成的编号
        //省去业务操作
        String baseNum = "xxxx03";
        
        //新生成编号保存至数据库
        baseService.save(baseNum);
        ..
        ..
        ..
        //业务代码
    }

在上面情况下发现有编号重复现象,于是尝试加锁解决,因为是多服务,使用分布式锁Redission,伪代码如下

	@Transaction(rollbackFor = Exception.class)
    public void test() {
        RLock lock = redissionClient.getLock("lock");
        boolean flag = lock.tryLock(5, 10, TimeUnit.SECONDS);
        if (flag) {
            try {
                //获取当前数据库编号信息并做一定处理得到生成的编号
                //省去业务操作
                String baseNum = "xxxx03";

                //新生成编号保存至数据库
                baseService.save(baseNum);
            } finally {
                lock.unlock();
            }
        }
        ..
        ..
        ..
        //业务代码
    }

2. Redission失效?

在使用上面方案后,发现还是会有重复编号出现,难道是Redission失效了?

这点应该不可能,于是开始对代码再次分析,整体代码只锁住了关于编号操作,是其他的模块导致的么?

于是试着将整块代码锁住,重复编号就没再出现。

回过头来,再次对代码分析,发现导致编号重复的是@Transaction这个注解,这段代码整体是一个事务,而事务有ACID四大特性,事务彼此隔离,即不可见,导致编号的修改对于其他事务是不可见的,如图所示,整体可以分成两部分
在这里插入图片描述
在这段代码中,由于事务不可见的特性,在当前事务完成过程中其他线程读取到数据库的值其实还是未操作的数据,从而导致数据重复。

于是将编号生成单独拆分出一个事务进行处理,问题到此结束。

重新温习事务四大特性
在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值