Redis 分布式锁(ReentrantLock + RedissonRedLock)
2021-02-25 21:51:42 112 举报
Redis分布式锁是一种用于解决分布式系统中并发问题的技术,它结合了ReentrantLock和RedissonRedLock两种实现方式。ReentrantLock是一种可重入的互斥锁,通过在Redis中设置一个特定的键值对来实现锁的功能。当一个线程获得锁后,其他线程需要等待或者放弃竞争。而RedissonRedLock则是基于Redisson库的一种实现方式,它通过尝试获取多个Redis节点上的锁来提高锁的可靠性和性能。当超过半数节点成功获取锁时,锁才会被认为已经获取成功。这种分布式锁技术可以有效地避免多个线程同时访问共享资源,从而保证了数据的一致性和系统的稳定性。
作者其他创作
大纲/内容
失败加锁
基于 Lua 加锁(有过期时间)
返回 null
基于上述的加锁流程(过期时间为 30 秒)
执行 hincrby 指令,减小重入次数
是,重新竞争加锁
使用 Redis subscribe 指令,订阅分布式锁的释放消息。
Redis 集群 A
Redisson 分布式锁的数据结构1、一个 Redis 分布式锁,对应一个 hash。hash 对应的 key 为分布式锁的名字。例如说,我们锁定某个商品的库存,则 key 可以是 \"product_stock_01\"2、hash 里面只有一对 field value 键值对。(field 指的是 hash 中的 key) 1)field 为锁定的 JVM 进程 + 线程编号的拼接,其中 JVM 进程编号为 UUID 生成。例如说,\"01d76a97-14b5-4760-9987-b2ebe544ba93:1024\"。注意,最后一个冒号后面的数字,为线程编号 2)value 为锁定的次数。因为 Redisson 分布式锁支持可重入性。3、为什么采用 hash 数据结构,而不是 string 结构呢?因为 Redisson 分布式锁支持可重入性,其必然需要存储一个锁定的来源,而 hash 对应的 key 必然是分布式锁的名字,因此只能通过 hash 的 field 来存储。
RedissonRedLock 红锁的加锁流程
应用
否
是否阻塞等待锁
value 是否是自己
基于 Lua 解锁
是否还有阻塞等待时间?
解锁失败返回 null
WatchDog(定时任务)
顺序加锁。是否还有需要加锁的?
某个线程
是(情况三)
失败加锁1. pttl 指令,获得锁的过期时间
key + field 是否存在
....
否(情况三)
成功加锁1. hincrby 指令,增加重入次数2. pexpire 指导,设置过期时间
示例
RedissonRedLock 红锁的解锁流程
是
Redis 集群 N
1. del 指令,删除 key,进行解锁2. pulish 指令,发布解锁的消息,从而通知阻塞等待的线程们 返回 1【已解锁】
是否在等待时间内,获取到释放消息?
当前加锁成功?
是(情况二)
是否加锁失败数量达到N / 2 - 1?
是,加锁
成功加锁1. hset 指令,设置锁的持有,且重入次数为 12. pexpire 指导,设置过期时间
否,释放加锁
是,解锁
首次执行
KEYS[1] 分布式锁名,即分布式锁对应的 hash 的 key。KEY2[2] 分布式锁对应的 Channel 的名字,用于 publish 消息。例如说,锁名为 anylock 对应的为 redisson_lock__channel{anylock}ARGV[1] 解锁消息ARGV[2] 锁的时长。减少一次锁的可重入性时,会刷新锁的超时时间ARGV[3] 获取锁的来源,即分布式锁对应的 hash 里的 field,为 JVM 进程 + 线程编号的拼接。
不带过期的加锁逻辑,比较特殊,实际是只要当前 JVM 进程存活,就一直持有锁到解锁为止。Redis 不存在类似 ZooKeeper 的 Session 保持机制。因此,Redisson 通过每次获取 30 秒的分布式锁,配合后台的 WatchDog 每 10 秒重新家锁的方式,进行实现类似的效果。注意,WatchDog 只有在加不过期的锁才会存在!!!
成功
Redis 集群 B
返回锁的过期时间
pexpire 指令,重新设置过期时间 返回 0【未解锁】
否(情况一)
彻底失败加锁
KEYS[1] 分布式锁名,即分布式锁对应的 hash 的 key。ARGV[1] 锁的时长ARGV[2] 获取锁的来源,即分布式锁对应的 hash 里的 field,为 JVM 进程 + 线程编号的拼接。
ReentrantLock 加锁流程(无过期时间)
是说明是自己的锁
key 是否存在
ReentrantLock 加锁流程(带过期时间)
友情提示:细节较多,可能画的有缺失
每 10 秒定制执行
是否加锁成功数量达到N / 2 + 1?
成功加锁
重入次数是否为 0
是,继续加锁
(加锁成功)加锁成功的实例,使用 expire 指令,设置过期
否,超时
(加锁失败)加锁成功的示例,进行解锁流程
否(情况二)
是,释放加锁
失败
ReentrantLock 解锁流程
0 条评论
下一页