一篇文章看懂Redission原理 2024-06-14 作者 C3P00 Redission 是一个基于 Redis 的 Java 客户端,它提供了一系列的分布式数据结构和服务,方便开发者在分布式环境下进行数据操作和通信。本文将深入探讨 Redission 的原理,并以可重入锁、锁重试和 WatchDog 机制、MutiLock 原理为例进行详细讲解。 ☃️可重入锁原理 Redission 的可重入锁利用 Redis 的 Hash 结构实现,它使用一个大 Key 来表示锁是否存在,并使用多个小 Key 来记录当前持有锁的线程信息。 加锁逻辑: 判断锁是否存在: 如果锁不存在,则使用 redis.call('hset', KEYS[1], ARGV[2], 1) 命令将锁信息写入 Redis 的 Hash 结构中,并设置过期时间。 判断锁是否被当前线程持有: 如果锁存在,则使用 redis.call('hexists', KEYS[1], ARGV[2]) 命令判断当前线程是否持有该锁。如果是,则使用 redis.call('hincrby', KEYS[1], ARGV[2], 1) 命令将锁的 value 值加 1,表示该线程再次获得了锁。 设置过期时间: 使用 redis.call('pexpire', KEYS[1], ARGV[1]) 命令为锁设置过期时间。 释放锁逻辑: 释放锁时,使用 redis.call('hincrby', KEYS[1], ARGV[2], -1) 命令将锁的 value 值减 1。当 value 值减至 0 时,表示该线程不再持有锁,锁被释放。 可重入机制: Redission 的可重入锁通过记录每个线程持有的锁次数来实现可重入机制。当一个线程第一次获得锁时,锁的 value 值为 1。如果该线程再次尝试获得锁,则 value 值会加 1,表示该线程再次获得了锁。只有当 value 值减至 0 时,该线程才真正释放锁。 ☃️锁重试和WatchDog机制 Redission 的锁重试机制是指当线程尝试获得锁失败时,会不断重试直到获得锁。WatchDog 机制则是为了防止锁在持有线程意外宕机时无法释放,而引入的一种自动续约机制。 锁重试: Redission 的锁重试机制通过 while(true) 循环实现,每次循环都会尝试获得锁。如果获得锁成功,则退出循环;否则,会根据 waitTime 和 leaseTime 参数来控制重试频率和重试时间。 WatchDog 机制: WatchDog 机制通过一个定时任务来实现,该定时任务会定期检查锁的剩余时间,并在剩余时间不足时进行续约。WatchDog 机制的核心代码如下: ttlRemainingFuture.onComplete((ttlRemaining, e) -> { if (e != null) { return; } // lock acquired if (ttlRemaining == null) { scheduleExpirationRenewal(threadId); } }); 这段代码会在锁获得成功后,启动一个定时任务,该定时任务会根据 internalLockLeaseTime 参数来设置续约时间。当定时任务触发时,会调用 renewExpirationAsync 方法来进行锁续约。 ☃️MutiLock原理 为了提高 Redis 的可用性,我们通常会搭建集群或者主从模式。在主从模式下,如果主机在将锁信息同步到从机之前宕机,则新的主机会丢失锁信息,导致锁失效。 为了解决这个问题,Redission 提出了 MutiLock 锁,它将锁信息写入到所有 Redis 节点中,只有所有节点都写入成功,才算加锁成功。 MutiLock 加锁原理: 将多个锁添加到一个集合中: Redission 会将需要加锁的所有锁添加到一个集合中。 循环尝试获取锁: Redission 会使用 while 循环,不断尝试获取集合中的所有锁。 设置总加锁时间: Redission 会设置一个总加锁时间,该时间等于需要加锁的个数乘以 1500 毫秒。 判断加锁是否成功: 如果在总加锁时间内,所有锁都获取成功,则加锁成功;否则,会再次进行重试。 MutiLock 的优势: 提高锁的可靠性: MutiLock 锁将锁信息写入所有 Redis 节点,即使某个节点宕机,也不会导致锁失效。 提高锁的可用性: MutiLock 锁可以提高锁的可用性,即使某个节点宕机,其他节点仍然可以正常提供服务。 参考文献 一篇文章看懂Redission原理-CSDN博客
Redission 是一个基于 Redis 的 Java 客户端,它提供了一系列的分布式数据结构和服务,方便开发者在分布式环境下进行数据操作和通信。本文将深入探讨 Redission 的原理,并以可重入锁、锁重试和 WatchDog 机制、MutiLock 原理为例进行详细讲解。
☃️可重入锁原理
Redission 的可重入锁利用 Redis 的 Hash 结构实现,它使用一个大 Key 来表示锁是否存在,并使用多个小 Key 来记录当前持有锁的线程信息。
加锁逻辑:
redis.call('hset', KEYS[1], ARGV[2], 1)
命令将锁信息写入 Redis 的 Hash 结构中,并设置过期时间。redis.call('hexists', KEYS[1], ARGV[2])
命令判断当前线程是否持有该锁。如果是,则使用redis.call('hincrby', KEYS[1], ARGV[2], 1)
命令将锁的 value 值加 1,表示该线程再次获得了锁。redis.call('pexpire', KEYS[1], ARGV[1])
命令为锁设置过期时间。释放锁逻辑:
释放锁时,使用
redis.call('hincrby', KEYS[1], ARGV[2], -1)
命令将锁的 value 值减 1。当 value 值减至 0 时,表示该线程不再持有锁,锁被释放。可重入机制:
Redission 的可重入锁通过记录每个线程持有的锁次数来实现可重入机制。当一个线程第一次获得锁时,锁的 value 值为 1。如果该线程再次尝试获得锁,则 value 值会加 1,表示该线程再次获得了锁。只有当 value 值减至 0 时,该线程才真正释放锁。
☃️锁重试和WatchDog机制
Redission 的锁重试机制是指当线程尝试获得锁失败时,会不断重试直到获得锁。WatchDog 机制则是为了防止锁在持有线程意外宕机时无法释放,而引入的一种自动续约机制。
锁重试:
Redission 的锁重试机制通过
while(true)
循环实现,每次循环都会尝试获得锁。如果获得锁成功,则退出循环;否则,会根据waitTime
和leaseTime
参数来控制重试频率和重试时间。WatchDog 机制:
WatchDog 机制通过一个定时任务来实现,该定时任务会定期检查锁的剩余时间,并在剩余时间不足时进行续约。WatchDog 机制的核心代码如下:
这段代码会在锁获得成功后,启动一个定时任务,该定时任务会根据
internalLockLeaseTime
参数来设置续约时间。当定时任务触发时,会调用renewExpirationAsync
方法来进行锁续约。☃️MutiLock原理
为了提高 Redis 的可用性,我们通常会搭建集群或者主从模式。在主从模式下,如果主机在将锁信息同步到从机之前宕机,则新的主机会丢失锁信息,导致锁失效。
为了解决这个问题,Redission 提出了 MutiLock 锁,它将锁信息写入到所有 Redis 节点中,只有所有节点都写入成功,才算加锁成功。
MutiLock 加锁原理:
while
循环,不断尝试获取集合中的所有锁。MutiLock 的优势:
参考文献