如何实现分布式锁

一、锁的作用

锁是为了解决多线程情况下,对于共享资源的访问安全问题。
但是当系统是分布式的时候,本地锁已经没法锁住所需要的资源,因为本地获取了锁,其他系统无法得知本地锁的情况。
分布式锁,是独立于系统的第一方实现的功能。因而状态可供不同系统获取。

二、分布式锁实现

2.1、基于redis实现

基于redis实现的分布式锁是当下比较流行的一种实现方式。
利用redis的set命令,用全路径类名方法名作为key,当前线程id作为value,插入一条记录,当且仅当该记录不存在。
如果返回1,代表成功获取到锁,返回0代表锁已经被其他线程获取了。
命令 格式:set key value nx ex 过期时间
释放锁的时候需要判断是否是自己加的锁,只能释放自己加的锁。

这样即可以防止系统挂掉导致无法释放锁的情况。不过又引入了锁内代码还没执行完就提前释放的情况,因此需要锁续期。可以设置一个守护线程,在快要到达第一次超时时间的时候启动守护线程,给锁续期,每隔所续的时间,再次启动守护线程续期。

2.2、基于数据库实现

利用数据库唯一索引来实现分布式锁。
建立一个分布式锁表,包含字段全路径类名、方法名,给全路径类名+方法名建立唯一索引。唯一索引会限制只有一个线程能成功插入数据。
获取锁的时候,就往数据库插入一条数据,如果插入成功,则代表获取到分布式锁。
释放锁的时候就删除该记录。

存在的问题:如果获取锁之后,数据库或者服务器挂了,那么分布式锁就没法释放。使用主从数据库可以解决数据库挂了的问题。服务器挂了的问题可以通过启动一个定时任务,根据记录创建时间,定时删除数据库超时的记录。

可以通过记录获取锁的主机信息和线程信息,如果查到已存在的记录属于当前线程,就将锁分配给他,实现可重入。

2.3、基于数据库排他锁实现

在查询语句的后面加上for update,数据库会启动排他锁,利用排他锁可以实现分布式锁。
用户查询到数据就代表他获取了锁,可以执行业务代码,最后commit提交释放排他锁。
数据库被加了排他锁之后,其他线程还想加排他锁就会被阻塞。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值