首页/案例库/分布式锁实现对比
进阶分布式系统

分布式锁实现对比

Redis vs ZooKeeper vs etcd 的锁机制对比

分布式系统中,多个服务实例同时操作共享资源需要互斥锁。Redis SETNX 简单高效但有单点问题,Redlock 跨多节点更可靠但存在争议;ZooKeeper 用临时顺序节点实现公平锁,强一致但性能较低;etcd 用租约(Lease)和事务实现,兼顾一致性和性能。本案例对比三种实现的原理、优缺点和适用场景,帮你选择合适的分布式锁方案。

分布式锁RedisZooKeeperetcdRedlock互斥
STEP_1
Redlock 需要 N 个独立 Redis 实例(非主从),通常 N=5
SETNX + TTL + LUA 脚本 — PROCESSING
redis-lock.log
// Redis 单节点锁
const lockKey = "lock:order:123"
const lockValue = crypto.randomUUID()  // 随机值标识持有者
const ttlMs = 30000

// 获取锁
const acquired = await redis.set(lockKey, lockValue, "NX", "PX", ttlMs)
if (!acquired) {
  throw new Error("获取锁失败")
}

try {
  // 执行业务逻辑
  await processOrder()
} finally {
  // 释放锁(Lua 脚本保证原子性)
  const script = `
    if redis.call("GET", KEYS[1]) == ARGV[1] then
      return redis.call("DEL", KEYS[1])
    else
      return 0
    end
  `
  await redis.eval(script, 1, lockKey, lockValue)
}

// Redlock 算法(伪代码)
async function redlock(key: string, ttl: number) {
  const startTime = Date.now()
  let successCount = 0
  
  // 并行向 N 个 Redis 实例获取锁
  for (const redis of redisInstances) {
    if (await redis.set(key, value, "NX", "PX", ttl)) {
      successCount++
    }
  }
  
  // 检查:多数派成功 + 耗时未超过 TTL
  const elapsed = Date.now() - startTime
  if (successCount >= N/2 + 1 && elapsed < ttl) {
    return true  // 获锁成功
  }
  
  // 失败则释放所有已获取的锁
  await releaseAll()
  return false
}

Redis 分布式锁Redis 单节点锁用 SET NX PX 原子命令:只有键不存在时才设置(互斥),同时设置过期时间(防死锁)。值用随机 UUID 标识锁持有者,释放时用 Lua 脚本检查值是否匹配再删除(防误删)。单节点锁的问题:主从切换时锁可能丢失。Redlock 在 N 个独立 Redis 实例上同时获取锁,多数派成功才算获锁,但 Martin Kleppmann 指出其在网络分区和时钟漂移场景下仍可能失败。

实时沙盒SANDBOX
CRITICAL
快速场景
手动调节
锁实现方式
选择分布式锁方���
选择适合业务场景的锁实现
并发竞争数
同时竞争锁的客户端数
10
并发数适中
模拟节点故障
所有节点正常
锁过期时间
防止死锁的 TTL
30 s
TTL 极短,极易导致并发问题