项目里哪些业务用过 Redis 分布式锁?锁过期、误删和主从切换问题怎么处理?
这个问题我会先说项目结论:Redis 分布式锁至少要使用 SET key uniqueValue NX PX ttl 原子加锁,锁值标识持有者,释放时通过 Lua 比较锁值后删除;还要处理业务超时、续期、重试、主从切换和进程暂停。
我会先交代项目背景和选型结论。从 SET NX PX、唯一锁值、Lua 解锁、续期到 Fencing Token 理解锁的边界。Redis 分布式锁至少要使用 SET key uniqueValue NX PX ttl 原子加锁,锁值标识持有者,释放时通过 Lua 比较锁值后删除;还要处理业务超时、续期、重试、主从切换和进程暂停。对于不能容忍旧持有者继续写入的关键资源,还需要 Fencing Token 或选择具备一致性保证的协调系统。
具体落地时,我会沿着实际调用链来讲。 SET NX PX:原子获取与租期。 EVAL compare-and-delete:只释放自己的锁。 我会先确认请求实际走到了哪条路径,再用运行数据验证,不会只看类名或配置猜测。
参数和容量不能靠默认值,我会结合业务量来定。注入超过租期的 STW、网络分区和释放重试;资源端记录 fencing token,验证旧持有者被拒绝。
效果要用数据证明,线上问题也要能闭环。固定输入和基线 先在没有故障注入的环境执行上述配置,固定数据规模、并发度、运行时版本和预热时间。以「持锁 P99」为主基线,记录值应满足「<租期 30%」;同时保存 获取等待与失败率、持锁时间分布,使后续变化能够回到同一时间轴比较。 线程获得 10 秒锁后发生 15 秒停顿,锁过期被另一实例取得;旧线程恢复后继续写库。仅有锁无法阻止过期持有者,数据库写入必须携带 fencing token 并拒绝较旧令牌。 无唯一锁值误删他人锁:获取等待与失败率:唯一 value+Lua 释放。 租期短于最坏执行时间:持锁时间分布:关键写携带 fencing token。
最后我会主动说明这个方案不适合什么场景。分布式锁提供互斥意图,不等于线性一致事务;关键资源应通过版本、唯一约束或 fencing 在最终写入点再次裁决。