Redisson的可重入锁

Redisson 的可重入锁可以拆成两件事:记录"谁"拿了锁,以及记录"拿了几次"。真正复杂的是因为它要在 Redis 里把这两件事都"持久化"下来,让分布式环境下的所有服务实例都认可。


锁的核心数据结构

  • Redis 用 Hash 结构存储锁,key 形如 lock:order。
  • Hash 的 field 是线程标识(如 thread1),value 是"重入次数"。
  • 如果 hash 里没有你的线程字段,说明锁要么未被占用,要么被别人占用。

加锁流程(看右边流程图)

  1. 判断锁是否存在
  • 不存在:创建 hash,写入 field=thread1,value=1,设置过期时间,拿锁成功。
  • 存在:继续判断是否是自己持有。

2.判断锁标识是否是自己

  • 是自己:重入次数 +1(HINCRBY),然后重置过期时间,继续执行。
  • 不是自己:加锁失败。

释放锁流程(看左侧 Lua 脚本)

  1. 确认锁还是自己持有
  • HEXISTS key threadId 判断 hash 中是否还有自己的 field;如果没有,说明锁早就被别人占了,直接返回。

2.重入次数减 1(HINCRBY -1)

  • 如果减完后仍然 > 0:说明还有重入层数未释放 → 只需重新设置过期时间,锁仍然归自己所有。
  • 如果减完 == 0:说明已经完全释放 → DEL key 删除整个锁。

为什么要这么设计?

  • 可重入:同一线程在调用链中多次 lock() 不会死锁,通过计数器记录。
  • 分布式:锁信息在 Redis 中,多个 JVM 实例都能看到。
  • 安全:在释放时通过线程标识校验防止误删他人锁。
  • 自动续期:每次重入或释放未结束时都重置 TTL,防止锁过期被别人抢走。

总结

Redisson 可重入锁就是:用 Redis 的 Hash 记录"哪个线程拿了锁 + 拿了几次",拿锁时只允许同一个线程的重入次数自增,释放时次数自减到 0 才真正删除锁,从而在分布式环境里实现和 Java ReentrantLock 类似的行为。

确实挺复杂,毕竟 Redisson 要在分布式环境里模拟 ReentrantLock 的行为,还要考虑线程标识、重入计数、自动续期、Redis 原子性等一堆细节。

好消息是:平时用它只需要 lock.lock() 和 lock.unlock(),内部的这些 Lua 脚本和状态管理都帮你处理好了。你只需知道它在做"记录线程+计数"的事情,调 API 就行。

相关推荐
惊讶的猫4 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
期待のcode4 小时前
Redis的主从复制与集群
运维·服务器·redis
jiunian_cn4 小时前
【Redis】渐进式遍历
数据库·redis·缓存
SoleMotive.5 小时前
谢飞机爆笑面经:Java大厂3轮12问真题拆解(Redis穿透/Kafka分区/MCP Agent)
redis·spring cloud·kafka·java面试·mcp
椰子今天很可爱5 小时前
Redis进阶
redis
jiunian_cn6 小时前
【Redis】数据库管理操作
数据库·redis·缓存
惊讶的猫6 小时前
Redis 哨兵(Sentinel)介绍
redis·redis哨兵
猫头虎6 小时前
基于信创openEuler系统安装部署OpenTeleDB开源数据库的实战教程
数据库·redis·sql·mysql·开源·nosql·database
静听山水6 小时前
Redis核心数据结构-ZSet
数据结构·redis
Dontla6 小时前
黑马大模型RAG与Agent智能体实战教程LangChain提示词——6、提示词工程(提示词优化、few-shot、金融文本信息抽取案例、金融文本匹配案例)
redis·金融·langchain