外观
单机锁和分布式锁最大的区别?
⭐ 题目日期:
美团 - 2024/12/23
📝 题解:
单机锁与分布式锁的核心区别在于 应用场景与实现机制,以下是详细对比:
1. 作用范围
类型 | 单机锁 | 分布式锁 |
---|---|---|
作用对象 | 同一进程内的多个线程 | 跨进程、跨机器的多个服务实例 |
典型场景 | 单应用内部资源竞争(如JVM内的共享变量) | 分布式系统共享资源(如数据库、文件、缓存) |
示例:
- 单机锁:Java的
synchronized
或ReentrantLock
,确保同一JVM内线程安全。 - 分布式锁:Redis的
RedLock
或ZooKeeper锁,协调多个服务实例对共享资源的访问。
2. 实现机制
类型 | 实现依赖 | 核心挑战 |
---|---|---|
单机锁 | 本地内存、线程调度机制(如CAS操作) | 仅需处理线程间竞争,无网络或节点故障问题 |
分布式锁 | 外部协调服务(如Redis、ZooKeeper) | 需解决网络延迟、分区容错、时钟同步、节点故障等 |
关键区别:
- 单机锁:通过操作系统或语言原生机制实现,性能高(无网络开销)。
- 分布式锁:依赖外部存储或共识算法,需处理网络超时、锁续期、脑裂等问题。
3. 可靠性要求
类型 | 可靠性问题 | 解决方案 |
---|---|---|
单机锁 | 线程死锁、锁泄露 | 代码优化(如避免嵌套锁)、设置超时 |
分布式锁 | 网络分区、锁失效、锁误删 | 租约机制(自动续期)、唯一标识验证、共识算法(如Paxos/Raft) |
示例:
- 分布式锁需通过 锁续期(Watchdog) 防止持有锁的节点宕机导致死锁。
- 使用 唯一Token(如UUID)确保只有锁持有者能释放锁,避免误删。
4. 性能对比
类型 | 性能特点 | 适用场景 |
---|---|---|
单机锁 | 微秒级延迟,高吞吐量 | 高并发单机应用(如本地缓存更新) |
分布式锁 | 毫秒级延迟(依赖网络),吞吐量较低 | 跨服务资源协调(如秒杀库存扣减) |
优化方向:
- 分布式锁可通过 本地缓存+异步同步 减少锁竞争(如Redisson的读写锁)。
- 单机锁可通过 无锁编程(如CAS) 或 分段锁 提升性能。
5. 典型实现方案
类型 | 实现技术 | 代表框架/工具 |
---|---|---|
单机锁 | 语言原生锁、并发工具类 | Java的synchronized 、ReentrantLock |
分布式锁 | 数据库、缓存、协调服务 | Redis的SETNX 、ZooKeeper临时节点、Etcd |
Redis分布式锁示例:
// 加锁(SET命令扩展参数:NX-不存在才设置,EX-超时时间)
String result = redis.set("lock_key", "token", "NX", "EX", 30);
if ("OK".equals(result)) {
try {
// 执行业务逻辑
} finally {
// 释放锁(Lua脚本保证原子性)
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
redis.eval(script, Collections.singletonList("lock_key"), Collections.singletonList("token"));
}
}
总结:最大区别
维度 | 单机锁 | 分布式锁 |
---|---|---|
核心目标 | 解决单进程内多线程资源竞争 | 解决跨进程、跨机器资源竞争 |
本质差异 | 依赖本地资源(内存/线程调度) | 依赖外部系统(网络、共识协议) |
复杂度 | 低(仅处理线程间同步) | 高(需处理网络分区、节点故障、时钟漂移等) |
选择建议:
- 单机锁:适用于单体应用或无需跨节点协调的场景。
- 分布式锁:必需在分布式系统中保证全局资源互斥访问时使用,但需谨慎处理性能和可靠性问题。