Redis 分布式锁的 Key 如何设计?
未标记
考查重点:互斥对象与锁键范围。锁键标识真正互斥的业务资源,如活动+商品;用户维度约束另建标识,避免全局大锁或包含随机值使锁失效
本题目录
参考答案
本答案基于相关资料,由 AI 辅助编写,供学习与面试准备参考。如有疏漏,欢迎反馈指正。
核心回答
锁的 Key 应标识真正需要互斥的业务资源,所有竞争者对同一资源必须算出同一个 Key。例如活动库存按“活动+商品”互斥,可用 lock:stock:{activityId:skuId};不同商品各自加锁,避免一把全局锁把所有请求串行化。
锁键里不放每次请求变化的随机数、线程号或时间戳,否则竞争者各锁各的,失去互斥效果。随机持有者标识放在锁的值里,用于续期和释放时确认身份。互斥资源标识、锁持有者标识和业务幂等标识是三种不同的东西。
先问清楚哪两个操作不能同时进行
库存扣减约束的是同一份库存;一人一单约束的是“活动+用户”;重复提交约束的是同一次业务操作。这三种约束不一定用同一个键,也不一定都需要分布式锁。
例如用户 u1 和 u2 购买同一商品,若库存修改需要互斥,它们必须竞争同一个库存资源键;只按用户加锁,仍然不能防止两人同时修改同一库存。反过来,对所有订单使用一个键,会让互不相关的订单彼此阻塞。
命名与实现细节
- 加上业务、环境或租户命名空间,避免不同系统恰好使用相同标识;编码分隔符,避免不同字段拼接成相同字符串。
- 键保持稳定且不过长;敏感信息可以用不可逆摘要或内部标识代替,不把完整个人信息放入可观察的键名。
- 若
Redis Cluster中的原子脚本需要操作多个键,再设计同槽的hash tag;不是所有键都加同一个标签,以免形成热点槽。 - 多资源操作约定固定加锁顺序,控制临界区和最长等待时间。
锁只能协调并发进入。订单去重仍需要稳定的幂等键、数据库唯一约束或状态条件更新;锁过期、客户端暂停和主从切换的风险也不会因为键名设计正确而自动消失。
参考资料
- 国内:JavaGuide:分布式锁:采用资源粒度、持有者校验和锁不能替代业务一致性的区分。
- 国内:JavaGuide:分布式锁实现方案:结合租期和失效风险,解释锁键设计正确仍不能排除客户端暂停、续约失败或主从切换的影响。
- 国内:阿里云:基于TairString实现分布式锁:核对加锁随机值、原子校验后释放与续租,避免误操作其他持有者。
- 国内:阿里云:Redis开发运维规范:采用业务命名空间、键长度和集群
hash tag的约束,解释锁键如何避免冲突与热点槽。 - 国外:Redis:Distributed Locks:核对租期和随机持有者值的作用,以及故障切换时互斥保证的边界。
- 国外:Redisson:Locks and synchronizers:核对
RLock只能由合法持有者释放的约束,区分共享资源键与锁持有者身份。
