基于SpringBoot与数据库表记录的方式实现分布式锁

同一进程内的不同线程操作共享资源时,我们只需要对资源加锁,比如利用JUC下的工具,就可以保证操作的正确性。对JUC不熟悉的同学,可以看看以下的几篇文章:

但是,为了高可用,我们的系统总是多副本的,分布在不同的机器上,以上同进程内的锁机制就不再起作用。为了保证多副本系统对共享资源的访问,我们引入了分布式锁。

分布式锁主要的实现方式有以下几种:

  • 基于数据库的,其中又细分为基于数据库的表记录、悲观锁、乐观锁
  • 基于缓存的,比如Redis
  • 基于Zookeeper的

今天演示一下最简单的分布式锁方案——基于数据库表记录的分布式锁

主要的原理就是利用数据库的唯一索引(对数据库的索引不了解的同学,可以参考我的另外一篇文章mysql索引简谈)

例如,有以下的一张表:

CREATE TABLE `test`.`Untitled`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增序号',
  `name` varchar(255) NOT NULL COMMENT '锁名称',
  `survival_time` int(11) NOT NULL COMMENT '存活时间,单位ms',
  `create_time` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `thread_name` varchar(255) NOT NULL COMMENT '线程名称',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `uk_name`(`name`) USING BTREE
) ENGINE = InnoDB ROW_FORMAT = Dynamic;

其中name字段加上了唯一索引,多条含有同样name值的新增操作,数据库只能保证仅有一个操作成功,其他操作都会被拒绝掉,并且抛出“重复键”的错误。

那么,当系统1准备获取分布式锁时,就尝试往数据库中插入一条name="key"的记录,如果插入成功,则代表获取锁成功。其他系统想要获取分布式锁,同样需要往数据库插入相同name的记录,当然数据库会报错,插入失败,也就代表着这些系统获取锁失败。当系统1想要释放掉锁时,删除掉此记录即可。thread_name列可以用来保证只能主动释放自己创建的锁。

我们希望实现的分布式锁有以下的效果:

  1. 获取锁是阻塞的,获取不到会一直阻塞
  2. 锁会失效,超过锁的生存时间后,会自动释放掉。这一点可以避免某些系统因为宕机而无法主动释放锁的问题

大致的流程图如下:

基于SpringBoot与数据库表记录的方式实现分布式锁

使用到了以下依赖࿱

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值