@@ -12,7 +12,7 @@ icon: "lock"
1212
1313下面是我对本地锁画的一张示意图。
1414
15- ![ 本地锁] ( ./images /distributed-lock/jvm-local-lock.png)
15+ ![ 本地锁] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/jvm-local-lock.png)
1616
1717从图中可以看出,这些线程访问共享资源是互斥的,同一时刻只有一个线程可以获取到本地锁访问共享资源。
1818
@@ -22,7 +22,7 @@ icon: "lock"
2222
2323下面是我对分布式锁画的一张示意图。
2424
25- ![ 分布式锁] ( ./images /distributed-lock/distributed-lock.png)
25+ ![ 分布式锁] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/distributed-lock.png)
2626
2727从图中可以看出,这些独立的进程中的线程访问共享资源是互斥的,同一时刻只有一个线程可以获取到分布式锁访问共享资源。
2828
6969end
7070```
7171
72- ![ Redis 实现简易分布式锁] ( ./images /distributed-lock/distributed-lock-setnx.png)
72+ ![ Redis 实现简易分布式锁] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/distributed-lock-setnx.png)
7373
7474这是一种最简易的 Redis 分布式锁实现,实现方式比较简单,性能也很高效。不过,这种方式实现分布式锁存在一些问题。就比如应用程序遇到一些问题比如释放锁的逻辑突然挂掉,可能会导致锁无法被释放,进而造成共享资源无法再被其他线程/进程访问。
7575
@@ -103,7 +103,7 @@ Redisson 是一个开源的 Java 语言 Redis 客户端,提供了很多开箱
103103
104104Redisson 中的分布式锁自带自动续期机制,使用起来非常简单,原理也比较简单,其提供了一个专门用来监控和续期锁的 ** Watch Dog( 看门狗)** ,如果操作共享资源的线程还未执行完成的话,Watch Dog 会不断地延长锁的过期时间,进而保证锁不会因为超时而被释放。
105105
106- ![ Redisson 看门狗自动续期] ( ./images /distributed-lock/distributed-lock-redisson-renew-expiration.png)
106+ ![ Redisson 看门狗自动续期] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/distributed-lock-redisson-renew-expiration.png)
107107
108108看门狗名字的由来于 ` getLockWatchdogTimeout() ` 方法,这个方法返回的是看门狗给锁续期的过期时间,默认为 30 秒([ redisson-3.17.6] ( https://github.com/redisson/redisson/releases/tag/redisson-3.17.6 ) )。
109109
@@ -207,19 +207,19 @@ lock.lock(10, TimeUnit.SECONDS);
207207
208208实际项目中,我们不需要自己手动实现,推荐使用我们上面提到的 ** Redisson** ,其内置了多种类型的锁比如可重入锁(Reentrant Lock)、自旋锁(Spin Lock)、公平锁(Fair Lock)、多重锁(MultiLock)、 红锁(RedLock)、 读写锁(ReadWriteLock)。
209209
210- ![ ] ( ./images /distributed-lock/redisson-readme-locks.png)
210+ ![ ] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/redisson-readme-locks.png)
211211
212212### Redis 如何解决集群情况下分布式锁的可靠性?
213213
214214为了避免单点故障,生产环境下的 Redis 服务通常是集群化部署的。
215215
216216Redis 集群下,上面介绍到的分布式锁的实现会存在一些问题。由于 Redis 集群数据同步到各个节点时是异步的,如果在 Redis 主节点获取到锁后,在没有同步到其他节点时,Redis 主节点宕机了,此时新的 Redis 主节点依然可以获取锁,所以多个应用服务就可以同时获取到锁。
217217
218- ![ ] ( ./images /distributed-lock/redis-master-slave-distributed-lock.png)
218+ ![ ] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/redis-master-slave-distributed-lock.png)
219219
220220针对这个问题,Redis 之父 antirez 设计了 [ Redlock 算法] ( https://redis.io/topics/distlock ) 来解决。
221221
222- ![ ] ( ./images /distributed-lock/distributed-lock-redis.io-realock.png)
222+ ![ ] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/distributed-lock-redis.io-realock.png)
223223
224224Redlock 算法的思想是让客户端向 Redis 集群中的多个独立的 Redis 实例依次请求申请加锁,如果客户端能够和半数以上的实例成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁,否则加锁失败。
225225
@@ -254,7 +254,7 @@ ZooKeeper 分布式锁是基于 **临时顺序节点** 和 **Watcher(事件监
2542542 . 成功获取锁的客户端在出现故障之后,对应的子节点由于是临时顺序节点,也会被自动删除,避免了锁无法被释放。
2552553 . 我们前面说的事件监听器其实监听的就是这个子节点删除事件,子节点删除就意味着锁被释放。
256256
257- ![ ] ( ./images /distributed-lock/distributed-lock-zookeeper.png)
257+ ![ ] ( https://oss.javaguide.cn/github/javaguide/distributed-system /distributed-lock/distributed-lock-zookeeper.png)
258258
259259实际项目中,推荐使用 Curator 来实现 ZooKeeper 分布式锁。Curator 是 Netflix 公司开源的一套 ZooKeeper Java 客户端框架,相比于 ZooKeeper 自带的客户端 zookeeper 来说,Curator 的封装更加完善,各种 API 都可以比较方便地使用。
260260
0 commit comments