60 秒回答模板

分布式锁用于多实例同时竞争同一资源时的跨节点互斥,例如同一 SKU 扣库存、同一订单状态推进、定时任务抢占、优惠券发放和防重复创建。回答时要先说明单机锁只能管一个进程,多副本部署后必须用 Redis、ZooKeeper、数据库等外部协调点。锁 key 要按资源粒度设计,拿锁后仍要二次校验业务状态,执行完用唯一 value 安全释放;长任务要续期,失败要幂等和补偿。分布式锁不是事务,能用唯一索引、乐观锁、队列串行化解决的场景不一定要加锁。

考点 核心机制与工程取舍
难度 中高频面试题
回答目标 按定义、机制、场景讲清楚

深入解析

01

业务动机是跨节点互斥

同一服务部署多台机器后,`synchronized` 或本地 mutex 只约束当前进程。多个实例同时修改同一资源时,需要一个所有实例都能看到的协调点。

02

场景要落到资源粒度

库存扣减可以按 `skuId` 加锁,订单流转按 `orderId` 加锁,定时任务按 `jobName` 抢占。粒度太粗会损失吞吐,粒度太细又可能保护不住共同资源。

03

锁内必须做状态二次校验

拿到锁只说明当前有进入临界区的资格,不代表业务一定可执行。还要重新查库存、订单状态或幂等记录,避免排队期间状态已经变化。

04

正确释放和续期是底线

Redis 锁至少要 `SET key value NX EX`,释放时用 Lua 比较 value 后删除,避免误删别人锁。执行时间可能超过 TTL 时,要么缩短临界区,要么用可靠续期并处理续期失败。

05

知道什么时候不用锁

唯一资源创建可用数据库唯一索引,扣库存可用乐观锁版本号,任务可用 MQ 分区串行或 actor 模型。锁会引入延迟、死锁和可用性依赖,不应默认套用。

易错点

  • 把分布式锁当数据库事务,拿锁后不做业务状态校验。
  • Redis 释放锁不比较唯一 value,可能删掉别人的锁。
  • 锁范围过大,把网络调用和耗时计算都放进临界区。
  • 不考虑锁过期、续期失败、进程崩溃和补偿路径。

面试官追问

分布式锁能解决所有并发问题吗?

不能。它只保护锁覆盖的临界区,数据库写入仍要唯一约束、状态机校验和幂等,锁失效后还要补偿。

锁超时时间怎么设置?

要覆盖正常业务耗时并留余量,同时不能过长导致故障后资源长期不可用。长任务优先拆短临界区,否则需要续期和续期失败处理。

锁过期但业务还在执行怎么办?

可能出现新持有者进入临界区,旧持有者继续写。强一致写入要配 fencing token、版本号或状态机拒绝旧请求。

锁粒度怎么设计?

按真正共享的资源设计。能按订单、用户、SKU 拆就不要全局锁;但跨多个资源时要固定加锁顺序或改用事务/队列,避免死锁。