Skip to content

Redis RedLock 和 ZooKeeper 分布式锁实现方案

以下是 分布式锁的两种主流实现方案(Redis RedLock 和 ZooKeeper) 的详细对比及适用场景分析:


一、分布式锁的核心要求

  1. 互斥性:同一时刻只有一个客户端持有锁。
  2. 容错性:锁服务需具备高可用(即使部分节点宕机,锁功能仍正常)。
  3. 避免死锁:持有锁的客户端崩溃后,锁能自动释放。
  4. 可重入性(可选):同一客户端可多次获取同一把锁。

二、Redis RedLock 分布式锁

1. 实现原理

RedLock 算法基于多个独立的 Redis 节点(通常 5 个),通过 多数派原则 确保锁的安全性:

  1. 获取锁
  • 客户端向所有 Redis 节点发送 SET key random_value NX PX 30000(随机值 + 超时时间)。
  • 若超过半数(N/2 +1)节点成功设置,则视为获取锁成功。
  1. 释放锁
  • 向所有节点发送 Lua 脚本,仅当值匹配时删除键(避免误删其他客户端的锁)。

2. 关键代码示例

python
# 获取锁
def acquire_lock(servers, resource, ttl):
    val = str(uuid.uuid4())
    success_count = 0
    for server in servers:
        if server.set(resource, val, nx=True, px=ttl):
            success_count += 1
    if success_count > len(servers) // 2:
        return val  # 锁获取成功
    else:
        # 释放已获取的锁
        release_lock(servers, resource, val)
        return None

# 释放锁(Lua 脚本保证原子性)
def release_lock(servers, resource, val):
    script = """
    if redis.call("get", KEYS[1]) == ARGV[1] then
        return redis.call("del", KEYS[1])
    else
        return 0
    end
    """
    for server in servers:
        server.eval(script, 1, resource, val)

3. 优点

  • 高性能:基于内存操作,吞吐量高。
  • 容错性:半数节点存活即可工作。

4. 缺点

  • 时钟依赖:依赖系统时钟一致性,时钟跳跃可能导致锁失效。
  • 网络延迟风险:若客户端因 GC 停顿导致锁过期,可能引发并发问题。

5. 适用场景

  • 高并发、低延迟:如秒杀库存扣减、分布式任务调度。
  • 允许极低概率的锁冲突:对一致性要求稍宽松的场景。

三、ZooKeeper 分布式锁

1. 实现原理

基于 ZooKeeper 的 临时顺序节点(Ephemeral Sequential Node)Watcher 机制

  1. 获取锁
  • 客户端在锁路径下创建临时顺序节点(如 /locks/resource_00000001)。
  • 检查自己是否是最小序号节点,若是则获取锁;否则监听前一个节点的删除事件。
  1. 释放锁
  • 客户端主动删除节点,或会话超时后 ZooKeeper 自动删除临时节点。

2. 关键代码示例(Curator 框架)

java
InterProcessMutex lock = new InterProcessMutex(client, "/locks/resource");
try {
    if (lock.acquire(30, TimeUnit.SECONDS)) {
        // 执行业务逻辑
    }
} finally {
    lock.release();
}

3. 优点

  • 强一致性:ZooKeeper 的 Zab 协议保证数据一致性。
  • 无时钟依赖:基于会话机制,避免时钟问题。
  • 自动释放:客户端崩溃后,临时节点自动删除。

4. 缺点

  • 性能较低:写操作需集群同步,吞吐量低于 Redis。
  • 运维复杂度:需维护 ZooKeeper 集群。

5. 适用场景

  • 强一致性要求:如金融交易、配置管理。
  • 长事务场景:客户端需长时间持有锁(依赖会话心跳机制)。

四、对比总结

维度Redis RedLockZooKeeper
一致性最终一致性(可能锁冲突)强一致性(CP 系统)
性能高(10k+ QPS)中(1k~5k QPS)
容错性半数节点存活即可工作半数节点存活即可工作
锁释放机制依赖超时自动释放临时节点自动释放 + 客户端主动释放
实现复杂度需处理时钟漂移、锁续期依赖 ZooKeeper 原生特性,实现简单
适用场景高并发、允许偶发锁失效强一致性、长事务、复杂协调场景

五、选型建议

  1. 优先选择 Redis RedLock
  • 需要高吞吐、低延迟。
  • 接受极小概率的锁失效(如缓存更新、限流控制)。
  1. 优先选择 ZooKeeper
  • 要求强一致性、锁绝对可靠(如订单支付、库存扣减)。
  • 需要监听锁状态变化(如 Master 选举)。
  1. 混合使用
  • 核心业务用 ZooKeeper 保证强一致性。
  • 非核心业务用 Redis 提升性能。

六、避坑指南

1. Redis RedLock 注意事项

  • 时钟同步:确保所有 Redis 节点使用 NTP 同步时钟。
  • 锁续期:通过看门狗线程(如 Redisson 的 lockWatchdogTimeout)定期续期,避免业务未完成锁过期。

2. ZooKeeper 注意事项

  • 会话超时:合理设置 sessionTimeout(默认 60s),避免网络波动导致锁释放。
  • 重试策略:处理 ConnectionLossException 等异常,确保锁操作幂等性。

3. 通用建议

  • 锁粒度:尽量细化锁的粒度(如按资源 ID 加锁)。
  • 监控告警:跟踪锁等待时间、持有时间,及时发现死锁或性能瓶颈。

文章来源于自己总结和网络转载,内容如有任何问题,请大佬斧正!联系我