基于数据库来实现分布式锁

由于锁不能夸跨jvm,在分布式服务中单体锁就会失效,所以需要借助第三方来实现锁的效果。

一、基于数据库悲观加锁来实现分布式锁

关于使用到数据库 select * from ... for update (悲观锁),会锁住查询出来的行数据,直到commit。具体请自行查阅,以下给出命令参考。

先开一个会话,关闭会话的自动提交,选一个数据select * from ... for update 加锁,

在此期间,在开一个会话,使用select * from ... for update给同一条数据加锁,由于一开始的会话已经给此数据加锁,所以会一直等待,直到最初的会话手动commit,新会话才能再次给同一条数据加锁。

-- 查看当前会话是自动提交还是手动提交(1 自动提交,0 手动提交)
select @@autocommit;

-- 设置当前会话为手动提交
set @@autocommit = 0;

-- select * from ... for update (悲观锁)
SELECT * FROM `distribute_lock` where business_code = 'demo' for update

-- 手动提交
commit;

利用select * from ... for update借助数据库,实现分布式锁


1、新建springboot项目,写一个dao和对应的xml(就是要使用for update),内容如下(自行根据表内容更改)

<select id="selectByCodeLock" resultType="com.xpf.distributelock.pojo.DistributeLock">
    SELECT * FROM `distribute_lock` where business_code = #{businessCode} for update
</select>

2、新建controller类demo

@RestController
@Slf4j
@RequestMapping("demoController")
public class DBLockController {

    @Resource
    private DistributeLockMapper distributeLockMapper;

    //开始事务,让整个方法执行完在提交,而不是数据库自动的在上锁后提交
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("singleLock")
    public String singleLock(){
        log.info("我进入了方法");
        DistributeLock distributeLock = distributeLockMapper.selectByCodeLock("demo");
        if (distributeLock == null){
            throw new RuntimeException("分布式找不到锁");
        }
        try {
            log.info("我进入了锁");
            Thread.sleep(15000);
        } catch (Exception e) {
            log.info(e.getMessage());
        }

        return "我已经执行完毕!";
    }
}

3、启动项目,然后复制配置在多启动一个相同的项目,端口改成8081。模拟分布式服务。

 4、用postman分别访问8080和8081这两个服务。

一开始访问8080,控制台输出如下

 获得了锁

然后访问8081,控制台输出如下

 分析,在8080给行数据锁之后,8081就需要等待8080业务执行完毕(模拟业务耗时,休眠了15s),并且事务提交后(必须开启事务或者说必须关闭数据库会话的自动提交,不然数据库上锁之后就自动提交了,不会等到下面的业务代码执行),才能给行数据加锁。

继续等待15s,控制台内容如下

 结果符合预期

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值