标准答案

  1. 使用 SET key token NX PX ttl 一次完成加锁和过期设置。
  2. 释放时用 Lua 或存储层原子操作比较 value 是否等于自己的 token,匹配才删除。
  3. 锁过期后旧持有者可能继续工作,关键写入仍需版本或 fencing 保护。

题目解析

获取锁时用唯一 token、NX 和过期时间组成一次原子操作,避免锁永久遗留或两个客户端同时认为自己成功。token 只属于当前持有者,不能使用固定值。

释放必须在存储层原子比较 token 后删除。先 GET 再 DEL 存在竞态:读取后锁可能过期并被新持有者获得,旧持有者随后会误删新锁。

锁的 TTL 到期后,旧持有者可能仍在执行;长任务需要续租、取消和 fencing,最终业务写入还要校验版本,不能把“拿到锁”当作完成证明。

代码示例

安全释放的原子语义:

Lua
if redis.call("get", KEYS[1]) == ARGV[1] then
  return redis.call("del", KEYS[1])
end
return 0

常见误区

  • 误区:获取和设置 TTL 分成两个命令。改正:使用一次原子 SET NX PX 或等价事务,避免中间崩溃留下永不过期锁。
  • 误区:释放时直接 DEL。改正:比较持有者 token 后原子删除,防止旧持有者误删新锁。
  • 误区:锁过期后继续无条件写入业务资源。改正:使用 fencing 或存储层版本校验,拒绝过期持有者。

作者信息