STEP_1
Redlock 需要 N 个独立 Redis 实例(非主从),通常 N=5SETNX + 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 极短,极易导致并发问题