← 返回题目列表

分布式锁为什么要记录持有者身份?

中等 第 22 / 26 题 更新于 2026/10/06
分布式锁Owner Token安全释放ABA
学习 AI 实战项目

简化版

锁记录持有者身份,是为了让续期和释放只能作用于本次获取创建的锁。若只按 key 删除,旧客户端在自己的锁过期后可能删掉新客户端刚获得的锁;value 应使用每次获取唯一的 owner token,并通过原子比较后操作。

详细版

owner token 不能只用线程号、IP 或固定实例 ID,因为重启、并发线程和容器复制会复用身份。常见做法是 instanceId + processEpoch + randomRequestId,重入锁还需保存持有计数;释放与续期使用 Lua/CAS 原子判断 value。

身份解决的是“谁能管理这条租约”,并不能判断持有者的新旧代次。旧 owner 在租约过期后继续写资源时,需要 Fencing Token;业务请求重复仍需要幂等键。日志可记录 token 摘要用于诊断,但不应把可伪造身份交给不可信客户端。

完整版教学

一、没有身份会发生误删

A 获得 10 秒锁后暂停 15 秒;锁过期,B 随即获得同一 key。A 恢复后执行无条件删除,删掉的是 B 的锁,C 又可进入临界区。锁服务从未同时保存两条记录,但错误释放制造了三个并发执行者。

记忆钩子:key 说明锁的是谁,value 说明这一代锁属于谁。

二、正确的原子释放

身份校验与状态修改必须是锁服务眼中的一个原子操作,否则校验通过后锁仍可能换代。不同后端可以用事务、CAS 或带 owner 条件的删除实现;调用方还必须检查操作结果,不能把“请求已发出”当作释放成功。

release(key, expectedOwner):
  atomically delete only if currentOwner == expectedOwner

条件不成立表示自己已不是 owner,应记录而不能扩大为无条件清理。Redis 中如何用 Lua 落实该原子条件,属于具体实现层面的另一道题。

原子操作最好返回“已修改、owner 不匹配或记录不存在”等可区分结果,便于判断是正常过期、重复释放,还是锁生命周期异常。

三、身份应怎样生成

每次成功获取都要有不可预测且几乎不重复的 token。只用 IP 会被同机多线程共享,只用线程号会在进程重启后复用,只用固定实例 ID 会让旧请求与新请求无法区分。可组合稳定实例 ID、启动 epoch 与随机 UUID,并控制长度。

身份方案主要问题
IP 地址NAT、容器与多线程复用
线程 ID重启后复用、跨进程冲突
固定实例 ID同实例不同获取无法区分
每次随机 token适合普通不可重入锁

四、续期也必须校验 Owner

旧客户端的定时器可能在锁过期后才执行。如果续期只按 key 延长 TTL,它会替 B 续期并误以为自己恢复了所有权。比较 owner 后续期能确保只有当前代租约被延长;释放、续期、重入计数修改都遵循相同原则。

客户端本地要把 token 与锁句柄绑定,不允许业务代码仅凭 key 调用 unlock。API 设计应让错误用法难以发生。

五、可重入与所有权传播

同一逻辑执行流重入时,可在 value 中保存 owner 和计数,第一次获取计数 1,再次获取加 1,只有减到 0 才删除。异步线程切换会让“当前线程”概念失效,应显式传播锁上下文,或禁止跨线程重入。

把 token 传给另一个服务等于委托管理权限,必须限制调用边界。一般只由持锁组件释放,下游接收的是 fencing 代次而非解锁凭证。

六、Owner 与 Fencing 的区别

owner token 通常只要求唯一,回答“这条锁记录是不是我的”;fencing token 必须单调,回答“这个操作是不是比资源见过的更新”。UUID owner 可防误删,却无法让数据库在 token A、B 之间判断哪个更晚。

日志记录 key hash、owner hash、获取时间和释放结果,监控 owner mismatch、锁过期与重复 unlock。owner mismatch 增多通常说明临界区超过租期或生命周期管理有 bug。

七、常见误区与追问

  • 误区:只有释放时需要 owner。 续期和重入计数修改同样需要校验。
  • 误区:实例 IP 可以唯一标识持有者。 IP 会复用且一个实例可能并发获取多次。
  • 误区:先 GET 再 DEL 已经安全。 两条命令之间存在 ABA 竞态。
  • 误区:UUID owner 能阻止旧主写数据。 资源侧无法从 UUID 判断新旧。
  • 追问:token 放在哪里? 锁 value 和客户端锁句柄中,日志仅保留摘要。
  • 追问:unlock 返回 0 怎么办? 视为已失去所有权,告警并停止后续副作用。
  • 追问:可重入锁如何表示? owner 加计数,并原子增减至零后删除。

八、加强记忆

Owner Identity 是锁生命周期的权限凭证:获取时每代唯一,续期和释放都原子比较,避免旧客户端操作新锁。它与业务幂等、Fencing Token 各司其职——owner 防误管租约,fencing 防迟到写,幂等防同一业务重复执行。