请阐述 Redisson 实现分布式锁的核心机制,包括加锁、解锁以及锁自动续期的具体流程。
考察说明
考查对 Redisson 分布式锁底层实现原理的掌握程度,重点在于 Redis 数据结构运用和看门狗机制。
回答思路
- 【回答框架 1】Redisson 分布式锁基于 Redis 的 SETNX 命令实现,但做了封装。加锁时,它会向 Redis 发送一个包含锁键、客户端唯一标识和过期时间的 Lua 脚本,确保原子性。键的值是一个哈希结构,存储持有锁的线程计数,支持重入。
- 【回答框架 2】锁默认的过期时间是 30 秒,但 Redisson 引入了看门狗机制。加锁成功后,如果未指定 leaseTime,后台会启动一个定时任务,每隔 10 秒(即锁过期时间的三分之一)检查锁是否仍被持有,若是则重置过期时间为 30 秒,防止业务未结束锁被自动释放。
- 【回答框架 3】解锁操作也通过 Lua 脚本实现。脚本会校验锁的值是否与当前客户端标识一致,一致才删除键,保证不会误删其他线程的锁。若锁已过期,删除失败,但此时业务可能仍在执行,存在一定风险。
- 【回答框架 4】对于锁的互斥性,当多个客户端同时加锁,只有一个能成功执行 SETNX 并返回,其他客户端会持续重试或订阅 Redis 的发布订阅消息,在锁被释放时被唤醒重新尝试。这保证了同一时刻只有一个线程能持有锁。
- 【回答框架 5】实际使用时需要关注锁的粒度,锁保护的业务范围应尽量小,避免长时间占用。同时,加锁和业务代码要处理异常,确保 finally 中释放锁,避免死锁。
- 【关键点 1】加锁通过 Lua 脚本实现原子操作,键为哈希结构,值为线程标识和重入计数。
- 【关键点 2】看门狗默认每 10 秒续期一次,将锁过期时间重置为 30 秒,需注意仅适用于未指定 leaseTime 的情况。
- 【关键点 3】解锁校验持有者身份,防止误删,使用 Lua 脚本保证原子性。
- 【关键点 4】锁的互斥依赖 SETNX 和 Redis 单线程特性,其他客户端等待锁释放。
- 【易错点 1】若业务执行时间超过锁过期时间且未正确续期,锁会被自动释放,导致临界区失控,需评估业务耗时。
- 【易错点 2】看门狗续期可能因网络分区或 Redis 故障而失效,造成锁提前失效,需考虑降级方案。
- 【易错点 3】锁的值仅标识客户端,若客户端在持有锁期间发生 GC 停顿,可能导致锁被其他线程获取,需结合其他机制控制。