← 每日面试题 学习看板

如何用Redisson实现分布式锁?

面试题/03数据库中间件/02Redis/07分布式锁/如何用Redisson实现分布式锁?.md

完整讲解(权威版)

最后更新:2026-11-01 · 基于第 1 次作答

L1 · 30 秒速记

结论:Redisson 用 Redis 的 Hash 结构 + Lua 脚本实现可重入分布式锁;getLock(key) 拿锁对象,lock()(看门狗自动续期)或 tryLock(waitTime, leaseTime) 拿锁,unlock() 校验持有者后释放。 关键词:Lua 原子 · Hash 可重入 · 看门狗续期 边界:锁需设过期防宕机死锁;看门狗只在未指定 leaseTime 时启用;单节点有单点故障需 RedLock。

L2 · 核心讲解

核心考点定位:考察 Redisson 分布式锁的底层机制(Lua 原子性、可重入、看门狗续期、解锁校验持有者),而非仅背 API;面试官想看到"为什么这样写才安全"。

机制链(≥3 环):

  1. getLock(key) → 返回 RLock 对象,绑定 Redis key(内部为 Hash)→ 加锁/解锁都走 Lua 脚本保证原子。
  2. lock() → Lua 脚本 SETNX + PEXPIRE,拿不到则订阅解锁通知阻塞等待 → 拿到锁后启动看门狗定时续期(默认 30s,每 1/3 续期)。
  3. 可重入 → Hash 的 field=线程 id、value=重入计数 → 同一线程重入计数加一;释放减一,减到 0 才真正删除 key。
  4. unlock() → Lua 校验持有者(field=当前线程 id)再删除 → 防误删他人锁;删除后发布解锁通知唤醒等待线程。

证据锚点:

对比与权衡:

方式原子性可重入自动续期释放安全
SETNX+EXPIRE 两步需 Lua 合成否否需校验
Redisson RLockLua 原子是(Hash 计数)看门狗校验持有者
单条 SET 命令原子否否易误删

常见误区:

  1. 错误:"SETNX 后单独 EXPIRE 就安全" → 正确:SETNX 与 EXPIRE 需合成一条原子命令或用 Lua,否则设置过期前进程崩溃会死锁 → 为什么:两步非原子,中间宕机导致锁永不过期。
  2. 错误:"unlock 直接 DEL key 就行" → 正确:必须校验 value=线程 id 再删,否则可能误删他人锁 → 为什么:锁超时后他人拿到锁,旧持有者 DEL 会误删新锁。
  3. 错误:"看门狗一直续期,锁永不释放" → 正确:看门狗只在持锁线程存活时续期,unlock 或线程死亡即停 → 为什么:续期与持锁生命周期绑定。
  4. 错误:"leaseTime 越短越好" → 正确:过短业务未完成锁被释放;不设则看门狗续期,设了则到期强制释放 → 为什么:过期时间要与业务执行时长匹配。

适用边界:

延伸追问(≥3)

  1. 为什么用 Lua 脚本?
  1. 看门狗如何续期?
  1. 可重入怎么实现?
  1. 锁超时误删如何防?

面试者参考回答

【结论】 Redisson 用 Redis 的 Hash + Lua 脚本实现可重入分布式锁;getLock(key) 拿锁,lock() 看门狗自动续期,unlock() 校验持有者后释放。

【三点】

第一,原子加锁:Lua 脚本 SETNX + PEXPIRE 原子执行;可重入用 Hash 的 field=线程 id、value=重入计数。

第二,自动续期:lock() 不设 leaseTime 时启动看门狗,默认 30s 每 1/3 续期,避免业务未完成锁过期。

第三,安全释放:unlock() 用 Lua 校验 value=当前线程 id 再删除,防误删他人锁;释放后发布通知唤醒等待线程。

【边界】 锁依赖 Redis 可用,需降级策略;单节点有单点故障用 RedLock;设置 leaseTime 则看门狗停用,需与业务执行时长匹配。

面试记录 2026-11-01(第 1 次)

题目:如何用 Redisson 实现分布式锁?

难度:medium

标签:redis/lock, redis/distributed-lock, general/knowledge, difficulty/medium

评分:⭐⭐⭐☆☆(3/5)

我的回答

redission中提供了分布式锁的实现,主要有两种方式获取锁,首先都需要通过定义一个key,通过getLock获取一个redisson定义的锁对象,然后可以选择支持看门狗的lock来实现获取锁,在执行结束后通过unlock解锁,或者通过tryLock设置一个有过期时间的锁,当然如果不设置过期时间,trylock也支持看门狗;但tryLock支持设置等待时间,如果等待时间到了就获取不到锁,走获取不到锁的流程

点评

评分:⭐⭐⭐☆☆(3/5)

优点:讲出 getLock(key) → lock()(看门狗)→ unlock();tryLock(waitTime/leaseTime,不设过期则看门狗);等待超时走获取失败流程。API 层面正确。

不足:漏了底层机制——Redis 锁用 Lua 脚本保证原子(SETNX+PEXPIRE/Hash 结构存线程 id);可重入(Hash field=线程 id、计数);解锁必须校验持有者(Lua 比较 value 再删);看门狗默认 30s、每 1/3 续期。

补充:补①Lua 原子加锁;②Hash 可重入计数;③解锁校验持有者防误删;④看门狗默认 30s/1/3 续期;⑤RedLock 多节点容错。

完整讲解见上方「完整讲解(权威版)」