目录
- 一、基于数据库的实现
- 1. 悲观锁(行锁)
- 2. 乐观锁(版本号)
- 二、基于 Redis 的实现
- 1. 单节点 Redis 锁
- 2. Redlock 算法
- 三、基于 ZooKeeper 的实现
- 四、基于 Etcd 的实现
- 五、其他实现
- 对比表格
- 选型建议
分布式锁是分布式系统中协调多节点并发访问共享资源的机制,其核心目标是保证在分布式环境下同一时刻只有一个客户端能执行关键操作。以下是常见的实现方式及其原理、优缺点和适用场景:
一、基于数据库的实现
1. 悲观锁(行锁)
- 原理:通过数据库的行锁机制(如
SELECT ... FOR UPDATE
)锁定记录。 - 优点:实现简单,直接利用数据库特性。
- 缺点:
- 性能差,高并发下数据库压力大。
- 锁释放依赖数据库连接,可能因连接断开导致死锁。
- 场景:低并发或已有数据库依赖的场景。
2. 乐观锁(版本号)
- 原理:在数据表中增加版本号字段,更新时校验版本号。
- 优点:无锁竞争,适合读多写少场景。
- 缺点:需自旋重试,可能增加业务复杂度。
- 场景:冲突较少的长事务场景。
二、基于 Redis 的实现
1. 单节点 Redis 锁
- 原理:使用
SET key value NX EX
命令设置带过期时间的键。 - 优点:性能高(10万+ QPS),实现简单。
- 缺点:
- 单点故障可能导致锁失效。
- 过期时间难以精确设置(如业务未完成锁已过期)。
- 改进:通过 Lua 脚本保证原子性,或使用 Redlock 算法。
2. Redlock 算法
- 原理:向多个独立 Redis 节点依次申请锁,多数节点获取成功才算获得锁。
- 优点:提升可用性,降低单点风险。
- 缺点:
- 部署复杂,需多个 Redis 实例。
- 性能下降(需多节点通信)。
- 场景:对一致性要求较高的场景(如金融系统)。
三、基于 ZooKeeper 的实现
- 原理:
- 创建临时有序节点(如
/lock/resource_00000001
)。 - 检查自己是否为最小节点,是则获得锁。
- 否则监听前一个节点的删除事件。
- 创建临时有序节点(如
- 优点:
- 高可靠性(CP 系统,强一致性)。
- 自动释放(连接断开时节点自动删除)。
- 缺点:
- 性能较低(万级 QPS)。
- 需维护 ZK 集群,复杂度高。
- 场景:对一致性要求极高的场景(如配置管理)。
四、基于 Etcd 的实现
- 原理:利用 Etcd 的租约(Lease)和事务(TXN)机制:
- 创建租约并绑定临时键值对。
- 通过事务比较版本号竞争锁。
- 优点:
- 高可用(基于 Raft 协议)。
- 支持自动续期和公平锁。
- 缺点:学习成本高,需熟悉 Etcd API。
- 场景:Kubernetes 生态或需要强一致性的系统。
五、其他实现
- Consul:通过 Session 机制和 Key-Value 存储实现锁。
- Chubby:Google 内部的分布式锁服务(类似 ZooKeeper 但更强调高可用)。
对比表格
实现方式 | 性能 | 一致性 | 可用性 | 复杂度 | 适用场景 |
---|---|---|---|---|---|
数据库行锁 | 低 | 强 | 低 | 低 | 低并发,已有数据库依赖 |
Redis 单节点 | 极高 | 弱 | 低 | 中 | 高并发,允许偶发锁失效 |
Redis Redlock | 高 | 较强 | 高 | 高 | 高并发,需更高可靠性 |
ZooKeeper | 中 | 强 | 高 | 高 | 强一致性,低频写操作 |
Etcd | 中高 | 强 | 高 | 高 | 云原生环境,强一致性需求 |
选型建议
- 一致性要求:强一致性选 ZooKeeper/Etcd,弱一致性选 Redis。
- 性能需求:高并发选 Redis,低频高可靠选 ZooKeeper。
- 运维成本:数据库方案简单,但 Redis/Etcd/ZK 需额外维护集群。
- 生态集成:Kubernetes 环境优先考虑 Etcd,大数据生态可选 ZooKeeper。
实际应用中需结合 CAP 权衡,例如 Redis 侧重 AP,ZooKeeper/Etcd 侧重 CP。同时建议结合具体客户端库(如 Redisson、Curator)简化开发。