分布式锁是后端面试高频题。很多候选人会直接说 Redis 的加锁和释放命令,或者说用数据库唯一索引。问题是,面试官往往会继续追问:为什么这里需要锁?锁过期了业务还没执行完怎么办?释放锁时会不会删掉别人的锁?锁没拿到是等待、失败还是降级?
分布式锁的回答顺序应该从业务风险开始,而不是从工具开始。
先讲需要互斥的业务动作
不是所有并发问题都需要分布式锁。适合讲锁的场景通常是同一个业务对象不能被多个请求同时修改,比如优惠券领取、库存扣减、定时任务单实例执行、同一用户重复提交、同一资源状态流转。
如果只是防重复创建,数据库唯一约束可能更直接;如果是控制执行顺序,状态机可能比锁更重要;如果是热点读请求,缓存和限流可能更合适。面试里能说出“不一定用锁”,反而更专业。
锁要有唯一标识和过期时间
加锁时通常需要设置过期时间,避免服务崩溃后锁永远不释放。但过期时间也会带来风险:业务还没执行完,锁先过期了,另一个请求拿到锁,两边同时执行。回答时要说明如何处理这个问题。
常见做法是合理估计业务执行时间,必要时做续期,也就是业务还活着时延长锁时间;释放锁时必须校验唯一标识,确认锁还是自己加的,避免误删别人的锁。这个唯一标识可以理解为锁的持有人凭证。
锁不是最终保障
真正稳的系统不会只靠锁。比如发券场景,锁可以降低并发冲突,但最终还要靠用户和券批次的唯一约束避免重复领取;库存扣减要有库存数量校验,不能只相信拿到锁;订单提交要有幂等请求号,避免网络重试造成重复业务。
面试官很喜欢追问“锁失效怎么办”。回答里要有兜底:唯一索引、状态机、事务校验、补偿任务和对账。锁只是并发控制手段,不是业务正确性的唯一来源。
一段更稳的项目表达
可以这样说:在优惠券领取场景里,我们用分布式锁控制同一用户同一活动的并发领取,避免瞬时重复请求打到数据库。锁设置过期时间,释放时校验锁的唯一标识,防止误删。即使锁异常失效,数据库里用户和券批次也有唯一约束兜底,业务层会把重复请求返回为已领取。上线后看锁竞争次数、领取失败原因、数据库唯一冲突次数和异常补偿记录。
这段回答没有把锁神化,而是把锁放在业务正确性的整体设计里。分布式锁面试真正考的,就是你知不知道工具边界。
锁要和业务后果绑定
分布式锁不是为了展示 Redis 命令,而是为了避免某个业务后果。面试里先说清楚不加锁会出什么错,再说锁怎么设计,答案会更自然。
| 业务后果 | 锁的作用 | 仍需补充 | 为什么 |
|---|---|---|---|
| 重复创建资源 | 限制同一业务键并发 | 唯一索引或幂等表 | 锁失败时数据库兜底 |
| 重复扣减 | 缩小并发窗口 | 条件更新和流水 | 锁不是最终一致性保证 |
| 定时任务多实例执行 | 只让一个实例处理 | 任务状态和超时恢复 | 防止执行中断后卡死 |
| 用户重复提交 | 控制短时间重复请求 | 请求幂等号 | 网络重试仍可能发生 |
高质量回答还要提释放锁的安全性:释放时要校验唯一标识,避免删掉别人的锁;锁过期时间要结合业务耗时,必要时续期或拆小任务。