极高 困难
Redis分布式锁#
一句话答案#
SETNX + 过期时间 + Lua 保证原子性,生产用 Redisson(Watch Dog 续期 + 可重入),注意主从切换时锁丢失。
核心要点
| 维度 | Redis 分布式锁 | ZooKeeper 分布式锁 |
|---|---|---|
| 实现原理 | SETNX + 过期时间 | 临时顺序节点 + Watch 机制 |
| 一致性 | AP(可能短暂不一致) | CP(强一致,ZAB 协议) |
| 性能 | 高(内存操作,单次命令) | 低(磁盘 IO,Zab 协议同步) |
| 锁释放 | 依赖 TTL 过期(可能有短暂延迟) | 客户端断开自动删除临时节点(更可靠) |
| 公平性 | 非公平(所有客户端竞争) | 公平(顺序节点保证 FIFO) |
| 脑裂风险 | 有(主从切换期间) | 低(多数派选举,不会双主) |
| 适用场景 | 对性能要求高,可接受极小概率失效 | 对正确性要求极高(金融、关键资源) |
面试回答(2分钟版)
Redis分布式锁的基本实现是用SET key uuid NX EX一条原子命令加锁,NX保证互斥,EX设过期时间防死锁,value存UUID标识持锁者。释放锁必须用Lua脚本保证判断value和删除key的原子性,防止误删别人的锁。核心问题是业务执行超过锁过期时间会导致并发,生产环境推荐Redisson框架,内置Watch Dog机制默认每10秒续期一次到30秒,还支持可重入锁,用Hash存线程标识和重入次数。另外Redis主从架构有缺陷:主节点加锁后未同步就宕机,从节点升主后锁丢失。Redis作者提出RedLock方案向N个独立节点加锁多数成功才算获锁,但该方案有争议,金融等强一致场景建议用ZooKeeper。
追问与易错
追问方向:
- “锁过期了但业务没执行完怎么办?”→ 使用 Redisson 的 Watch Dog 机制,加锁后每 10 秒自动续期到 30 秒,持锁线程存活期间锁不会过期;手动设置过期时间时 Watch Dog 不生效,需确保时间充足
- “主从切换时锁会丢失吗?怎么解决?”→ 会丢失,主库加锁后 binlog 未同步到从库就宕机,从库升主后锁不存在;RedLock 方案向 N 个独立 Redis 实例加锁,多数成功才算获锁,但该方案有争议不完全可靠
- “可重入锁怎么实现的?”→ Redisson 用 Hash 结构存储锁,field 为线程唯一标识(UUID+threadId),value 为重入次数;同一线程再次加锁时 value+1,释放时 value-1,减到 0 时删除 key
易错点:
- ❌ “SETNX + EXPIRE 两条命令”——不是原子操作!用 SET key val NX EX 一条
- ❌ “加了过期时间就安全了”——业务超时仍可能导致并发问题