【分布式】分布式锁

目录

一、什么是分布式锁?

二、为什么需要分布式锁?

三、如何实现分布式锁?

1. 要求

2. 实现方式

2.1 基于 Redis 实现分布式锁

2.2 基于 ZooKeeper 实现分布式锁

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


一、什么是分布式锁?

分布式锁是分布式系统中的锁,用来控制同一时刻,只有一个 JVM 进程中的一个线程可以访问被保护的资源。

二、为什么需要分布式锁?

对于单机多线程来说,在 Java 中,我们通常使用 ReetrantLock类、synchronized 关键字这类 JDK 自带的 本地锁 来控制一个 JVM 进程内的多个线程对本地共享资源的访问。

分布式系统下,不同的服务/客户端通常运行在独立的 JVM 进程上。如果多个 JVM 进程共享同一份资源的话,使用本地锁就没办法实现资源的互斥访问了。于是,分布式锁 就诞生了。

三、如何实现分布式锁?

1. 要求

一个最基本的分布式锁需要满足:

  • 互斥 :任意一个时刻,锁只能被一个线程持有;
  • 高可用 :锁服务是高可用的。并且,即使客户端的释放锁的代码逻辑出现问题,锁最终一定还是会被释放,不会影响其他线程对共享资源的访问。
  • 可重入:一个节点获取了锁之后,还可以再次获取锁。

2. 实现方式

实现方式基于 Redis基于 ZooKeeper基于数据库
性能一般
可靠性较可靠(AP架构)

可靠(CP架构)

不可靠(CA架构)
理解难易度一般困难容易
实现复杂度一般简单复杂
使用人数一般

2.1 基于 Redis 实现分布式锁

(1)实现 1:使用 setnx 进行加锁,使用 del 命令释放锁。

存在问题:如果已获取锁的线程发生异常,无法执行 del 命令释放锁,那么这个锁就一直占用,其他线程也获取不到这个锁。

(2)实现 2:加锁之后,使用 expire 命令设置锁超时时间。

存在问题:如果已获取锁的线程发生异常,还没来得及执行 expire 命令设置锁超时时间,那么这个锁也是一直占用,其他线程也获取不到这个锁。

(3)实现 3:Redis 2.6.X 之后,官方拓展了 set 命令的参数,满足了当 key 不存在则设置 value,同时设置锁超时时间,确保了原子性。命令格式:set <lock.key> <lock.value> nx ex <expireTime>

存在问题:1)如果已获取锁的线程 A 执行的很慢(如:网络问题、发生 FullGC……),过了锁超时时间还没执行完,而锁自动释放了,然后线程 B 获取了锁;2)线程 A 执行完,线程 B 还没执行完,线程 A 释放了线程 B 的锁。

(4)实现 4:加锁的时候设置一个唯一标识(比如线程 ID)作为 value 代表加锁的线程,释放锁时,先判断 key 对应的 value 是否匹配,必须匹配才能释放锁,可使用 Lua 脚本确保原子性。

存在问题:解决了实现 3 的问题 2),但是问题 1)的锁超时自动释放依然存在。

(5)实现 5Redisson,使用看门狗机制,获得锁的线程开启一个守护线程,用来给快要过期的锁续期。

2.2 基于 ZooKeeper 实现分布式锁

每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的临时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。 

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

(1)基于数据库表的增删

通过唯一索引保持排他性,加锁时插入一条记录,解锁是删除这条记录。

(2)基于数据库的排它锁

在查询语句后面增加for update,数据库会在查询过程中给数据库表增加排他锁。获得排它锁的线程即可获得分布式锁,当获得锁之后,可以执行方法的业务逻辑,执行完方法之后,释放锁connection.commit()。当某条记录被加上排他锁之后,其他线程无法获取排他锁并被阻塞。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值