标准答案
- 获取锁应使用原子方式设置唯一随机 token 和过期时间,避免先 SET NX 再单独 EXPIRE 时进程崩溃留下永久锁。
- 锁值必须标识当前持有者;释放时要比较 token 一致后再删除,避免旧请求误删后来者重新获得的锁。
- 锁要有合理租约,防止持有者崩溃后永久阻塞;但租约过期不表示旧持有者已经停止执行,关键写入仍需版本号、fencing token 或数据库条件更新保护。
- 很多场景根本不需要分布式锁。唯一约束、乐观锁、状态机、单分区消息或条件更新通常更容易验证且恢复路径更清楚。
题目解析
锁不是“让代码只跑一次”的魔法。网络延迟、进程暂停和 GC 停顿可能让持有者以为自己仍有锁,另一个请求却已获得新锁,因此下游必须能拒绝旧持有者的写入。
回答时应先说明临界资源和失败后果。若只是避免重复展示或重复计算,请求合并就够;若涉及扣款或库存,应把数据库约束放在最终防线。
常见误区
- SET NX 成功后不设过期时间,进程崩溃留下永久锁。
- 释放锁时直接 DEL,没有验证锁值。
- 把分布式锁当作唯一正确性机制,忽略数据库最终约束。