
分布式锁原理与源码
文章平均质量分 90
分布式锁的原理
东阳马生架构
回归初心,保持好奇心,享受那些"成功解题"的喜悦~
展开
-
分布式锁—7.Curator的分布式锁
然后获取当前客户端线程尝试获取锁时创建的临时顺序节点的名称,再根据名称获取在节点列表中的位置 + 是否可以获取锁 + 前一个节点的路径,也就是获取一个封装好这些信息的PredicateResults对象。当/semaphore/leases目录下的节点发生变化时,那些对该目录进行Watcher监听的客户端就会收到通知,于是就会执行Watcher里的process()方法,唤醒执行wait()时被阻塞的线程,从而让这些没有成功获取Semaphore的Lease的线程继续尝试获取Lease。原创 2025-03-08 23:01:03 · 809 阅读 · 0 评论 -
分布式锁—7.Curator的分布式锁二
在InterProcessReadWriteLock的readLockPredicate()方法中,如果是同一个客户端线程,先获取写锁,再获取读锁,是不会互斥的。当/semaphore/leases目录下的节点发生变化时,那些对该目录进行Watcher监听的客户端就会收到通知,于是就会执行Watcher里的process()方法,唤醒执行wait()时被阻塞的线程,从而让这些没有成功获取Semaphore的Lease的线程继续尝试获取Lease。等线程1释放了写锁后,才会唤醒线程2继续尝试获取写锁。原创 2025-03-08 22:56:38 · 716 阅读 · 0 评论 -
分布式锁—7.Curator的分布式锁一
然后获取当前客户端线程尝试获取锁时创建的临时顺序节点的名称,再根据名称获取在节点列表中的位置 + 是否可以获取锁 + 前一个节点的路径,也就是获取一个封装好这些信息的PredicateResults对象。具体会根据节点名称获取当前线程创建的临时顺序节点在节点列表的位置,然后会比较当前线程创建的节点的位置和maxLeases的大小。由于在节点列表里排第二的节点对应的线程会监听排第一的节点,而当持有锁的客户端线程释放锁后,排第一的节点会被删除掉。所以在节点列表里排第二的节点对应的客户端,便会收到zk的通知。原创 2025-03-08 22:55:17 · 1020 阅读 · 0 评论 -
分布式锁—6.Redisson的同步器组件
于是在这5个Master中,由于其中有一个是新切换过来的Master,所以只有2个Master是有客户端A加锁的数据,另外3个Master是没有锁的。但继续不幸的是,此时客户端B来加锁,那么客户端B就很有可能成功在没有锁数据的3个Master上加到锁,从而满足了过半数加锁的要求,最后也完成了加锁,依然发生重复加锁。每当客户端释放掉permits个锁,就会将信号量的值累加permits,这样Semaphore信号量的值就不再是0了。非公平锁,最基础的分布式锁,最常用的锁。情况一:先加读锁再加读锁,不互斥。原创 2025-03-07 22:38:48 · 1109 阅读 · 0 评论 -
分布式锁—5.Redisson的读写锁二
接着执行命令"del {myLock}:UUID1:ThreadID1:rwlock_timeout:1",即删除用来记录当前客户端线程第1个重入锁过期时间的key。然后接着执行命令"del {myLock}:UUID1:ThreadID1:rwlock_timeout:1",即删除用来记录当前客户端线程第1个重入锁过期时间的key。如果超过1,那么就遍历已被线程获取的所有重入和非重入的读锁,即遍历所有类似"{myLock}:UUID2:ThreadID2:rwlock_timeout:1"的key。原创 2025-03-06 22:20:47 · 920 阅读 · 0 评论 -
分布式锁—5.Redisson的读写锁一
首先执行命令"hget myLock mode",尝试获取一个Hash值mode,也就是从key为myLock的Hash值里获取一个field为mode的value值。然后根据key为UUID + 线程ID的Hash值,通过递减拼接,进行循环遍历,把每一个不同线程的读锁或同一个线程不同的重入锁,都刷新过期时间。WatchDog在处理读锁时,如果指定的线程还持有读锁,那么就会:刷新读锁key的过期时间为30秒,根据重入读锁的次数进行遍历,对重入读锁对应的key的过期时间也刷新为30秒。原创 2025-03-06 22:19:47 · 1336 阅读 · 0 评论 -
分布式锁—4.Redisson的联锁和红锁二
具体的处理就是在RedissonMultiLock的tryLock()方法中,当获取锁失败时,先判断是否达到加锁成功的最少数量。当发现failedLocksLimit为0,则表示此次获取联锁失败,需要释放获取的锁,同时重置failedLocksLimit的值 + 清空acquiredLocks + 复位锁列表的迭代器,为下一次尝试获取全部锁做准备。超时时间是毫秒级的,要远小于锁的有效时间,而且一般是几十毫秒。如果T2 - T1 < 锁的过期时间,则认为客户端加锁成功,否则加锁失败。原创 2025-03-05 23:03:54 · 744 阅读 · 0 评论 -
分布式锁—4.Redisson的联锁和红锁一
当发现failedLocksLimit为0,则表示此次获取联锁失败,需释放获取的锁,同时重置failedLocksLimit的值+清空acquiredLocks+复位锁列表的迭代器,为下一次尝试获取全部锁做准备。也就是说,如果第一次获取这n把锁时,在1500*n毫秒内无法获取这n把锁。在RedissonMultiLock的lockInterruptibly()方法中,会先根据联锁的个数来计算获取锁时的等待时间waitTime,然后通过while循环不停地尝试调用tryLock()方法去获取所有的锁。原创 2025-03-05 23:03:12 · 1080 阅读 · 0 评论 -
分布式锁—3.Redisson的公平锁二
判断锁是否已经被当前线程持有。在旧版本中,就不会刷新和延长有序集合中的超时时间分数,这样while循环的逻辑就会将这些宕机的客户端线程从队列中移出。接着,执行判断"lindex redisson_lock_queue:{myLock} 0 == UUID2:ThreadID2",由于队列存在,但是在队列中排第一的不是客户端B而是客户端C,所以条件不成立,客户端B无法加锁。在旧版本,随着时间推移,这些等待获取锁超时的线程只要不再尝试加锁,那么其等待获取锁的超时时间就不会更新被不断延长,就会被移除队列。原创 2025-03-04 23:23:27 · 1010 阅读 · 0 评论 -
分布式锁—3.Redisson的公平锁一
因为拥有最大过期时间的线程在队列中是排最后的,所以可通过队列中的最后一个元素的过期时间,计算当前线程的过期时间。使用Redisson的公平锁RedissonFairLock进行加锁时:首先调用的是RedissonLock的lock()方法,然后会调用RedissonLock的tryAcquire()方法,接着会调用RedissonLock的tryAcquireAsync()方法。如果获取到队列中的第一个元素,那么就会执行zscore命令:从有序集合中获取该元素对应的分数,也就是该元素对应线程的过期时间。原创 2025-03-04 23:22:50 · 1201 阅读 · 0 评论 -
分布式锁—2.Redisson的可重入锁二
也就是说,如果获取锁的线程还在持有锁,那么就重置锁的过期时间为30秒,并且lua脚本会返回1,接着在future.whenComplete()方法的回调中,继续调用RedissonBaseLock的renewExpiration()方法重新创建定时调度任务。如果获取锁的线程已经释放了锁,那么lua脚本就会返回0,接着在future.whenComplete()方法的回调中,会调用RedissonBaseLock的cancelExpirationRenewal()方法执行清理工作。原创 2025-03-03 21:40:18 · 676 阅读 · 0 评论 -
分布式锁—2.Redisson的可重入锁一
其中RedisExecutor的getConnection()方法会调用到MasterSlaveConnectionManager的connectionWriteOp()方法,该方法又会通过调用ConnectionManager的getEntry()方法根据slot值获取节点,也就是由ClusterConnectionManager的getEntry()方法去获取Redis的主节点。此时锁的超时时间会设为lockWatchdogTimeout默认的30秒,从而避免出现死锁的情况。原创 2025-03-03 21:39:19 · 956 阅读 · 0 评论 -
分布式锁—1.原理算法和使用建议二
获取到锁的线程会通过zk.delete()方法来删除其对应的节点实现释放锁,在等候获取锁的线程掉线时其对应的节点也会被删除。Redisson支持很多种复杂的锁的语义,提供了各种分布式锁的高级支持,Redisson这个客户端框架本身就有完整的一套Redis分布式锁实现。对于zk分布式锁,获取锁时创建的是临时节点,即便客户端挂了,由于临时节点会被zk删除,所以会自动释放锁。如果业务场景要求锁的语义健壮稳定,不能出现多客户端同时加到一把锁,且对锁的功能没有特别需求,那么可以使用zk分布式锁。原创 2025-02-28 23:40:59 · 1013 阅读 · 0 评论 -
分布式锁—1.原理算法和使用建议一
于是在这5个Master中,由于其中有一个是新切换过来的Master,所以只有2个Master是有客户端A加锁的数据,另外3个Master是没有锁的。即使大多数节点加锁成功,但如果加锁的累计耗时已超过锁的过期时间,那此时有些节点上的锁可能已经失效了,这个锁就没有意义了。所以释放锁时,不管之前有没有加锁成功,都需要释放所有节点的锁。这就是Redis作者在反驳中提到的:如果客户端已经拿到了锁,但客户端与锁服务器发生失联(例如GC),那不仅RedLock有问题,其它锁服务都有类似的问题,zk也是一样。原创 2025-02-28 23:39:58 · 1313 阅读 · 0 评论