Redisson分布式锁源码太复杂了,带你慢慢捋一捋那些细节和原理
- 问答
- 2025-12-27 22:22:04
- 4
综合自多位技术博主如“程序员小富”、“小黑盒”等关于Redisson分布式锁的源码解析文章)
Redisson分布式锁的源码确实比我们平时简单用一下要复杂得多,因为它考虑了很多在分布式环境下才会出现的极端情况,咱们今天就不说那些高大上的术语,就把它当成一个实用的工具,看看它到底是怎么工作的,为什么这么设计。
第一部分:最简单的加锁,背后可不简单
我们最常用的就是RLock lock = redisson.getLock("myLock"); lock.lock();,你看代码很简单,但Redisson在背后帮你做了好多事。

它并不是只往Redis里简单设置一个key就完事了,如果只是用Redis的SET key value NX命令(NX表示只有当key不存在时才设置),那确实能实现一个最基础的锁,但问题很多,某个客户端加锁后,因为网络问题或者自己崩溃了,没能及时释放锁,这个锁就永远解不开了,其他客户端再也拿不到锁,这就是死锁。
所以Redisson的加锁命令其实是一段Lua脚本,Lua脚本的好处是能保证一系列Redis命令的原子性执行,要么都成功,要么都失败,我们来看看它大概做了哪几件事(根据源码逻辑概括):
- 检查锁是否存在:首先看
myLock这个key在Redis里存不存在。 - 不存在就加锁:如果不存在,就用
hset命令创建一个Hash结构的数据,key是myLock,Hash里的一个字段是客户端的唯一标识(比如UUID+线程ID),值是这个锁被重入的次数(初始为1),它会设置这个key的过期时间。
这里的关键点来了:把锁的持有者信息和重入次数放在了Hash结构里,为什么?就是为了支持可重入,同一个线程可以多次调用lock(),每次重入,那个重入次数的值就加1,释放锁的时候,次数减1,直到减到0才真正删除这个key,这就避免了同一个线程自己把自己锁死的尴尬。

- 设置过期时间:这是解决死锁问题的核心,即使客户端挂了,锁到了过期时间也会自动释放。
第二部分:看门狗机制,锁的“续命”大师
刚才说了设置过期时间,那过期时间设多久呢?如果你在调用lock()时没有指定时间,Redisson会使用一个默认时间,通常是30秒,但问题来了,如果我的业务逻辑执行超过了30秒怎么办?锁过期自动释放了,别的客户端就能拿到锁,导致数据混乱。
Redisson的解决方案非常巧妙,叫“看门狗机制”(Watchdog),当你没有指定锁的超时时间时,这个机制就会启动,它的工作原理是这样的:

- 加锁成功后,Redisson会启动一个后台定时任务(一个线程),这个任务就像是锁的“看门狗”。
- 它每隔一段时间(默认是锁过期时间的1/3,比如30秒过期,就每10秒检查一次),都会去检查一下当前客户端是否还持有这个锁(通过检查Redis中那个Hash结构的客户端ID是否还是自己)。
- 如果还是自己持有的,它就“续命”,即重新设置一下锁的过期时间,重置为30秒。
- 只要你的应用程序还在正常运行,这个“看门狗”就会不断地给锁续期,直到你主动调用
unlock()方法释放锁,或者程序崩溃(程序崩溃了,看门狗线程也没了,自然就没人续命了)。
这个设计的好处是,锁的持有期和你业务逻辑的执行时间解耦了,只要你的应用进程活着,并且没有主动释放锁,锁就会一直被持有,避免了因为业务执行时间长而意外释放锁的问题。
第三部分:释放锁,也要小心翼翼
释放锁lock.unlock()同样是用Lua脚本来完成的,保证原子性,它主要做两件事:
- 检查当前要释放锁的客户端是不是锁的实际持有者(通过比较Hash结构里的客户端ID),如果不是,那就抛异常或者忽略,防止误释放别人的锁。
- 如果是持有者,就把重入次数减1,如果减1后重入次数大于0,说明这个线程还在重入状态,不需要做其他操作;如果减到0了,说明这是最后一次释放,那么就直接删除
myLock这个key,锁就被彻底释放了。
第四部分:高可用和公平锁
除了这些基本功能,Redisson还考虑了更多。
- Redisson RedLock(红锁):这是为了解决在Redis主从架构下,主节点宕机可能导致锁丢失的问题,红锁的原理是同时向多个(奇数个)独立的Redis节点申请加锁,只有当超过半数的节点都加锁成功时,才算加锁成功,这样即使某个主节点宕机,由于数据还没来得及同步到从节点,也不会影响锁的可靠性,不过这个算法争议也比较大,需要谨慎使用。
- 公平锁:普通的分布式锁是非公平的,谁抢到算谁的,Redisson也提供了公平锁的实现,它利用Redis的队列机制,让客户端按照申请锁的顺序来获取锁,先到先得。
Redisson分布式锁的源码之所以复杂,是因为它把一个生产环境中可能遇到的各种坑都想到了,并且给出了解决方案:用Lua脚本保证原子性、用Hash结构支持可重入、用看门狗机制解决死锁和锁超时问题、还提供了红锁和公平锁等高级特性,我们平时简单的一行lock()方法调用,背后其实是这样一个健壮而复杂的系统在支撑。
本文由瞿欣合于2025-12-27发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/69664.html
