标准答案
- 使用 SET key token NX PX ttl 一次完成加锁和过期设置。
- 释放时用 Lua 或存储层原子操作比较 value 是否等于自己的 token,匹配才删除。
- 锁过期后旧持有者可能继续工作,关键写入仍需版本或 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 或存储层版本校验,拒绝过期持有者。