

新闻资讯
技术学院Redis分布式锁易丢锁因GC或网络抖动致key过期,A恢复后误删B的锁;需UUID+Lua校验value、合理设超时、避免主从异步复制问题。
Redis 实现分布式锁最常见的是用 SET key value NX PX timeout,但仅靠这一条命令无法应对所有异常场景。比如客户端 A 拿到锁后,在业务执行中发生 GC 停顿或网络抖动,导致 Redis 中的 key 过期被自动删除;此时客户端 B 顺利加锁,A 恢复后仍按原逻辑执行释放操作——它会误删 B 的锁。
value,释放锁时通过 Lua 脚本比对 value 再 DEL,避免误删Zookeeper 的分布式锁本质是利用 EPHEMERAL_SEQUENTIAL 节点和 Watch 机制。每个客户端在指定路径(如 /lock)下创建临时顺序子节点,然后检查自己是否是序号最小的节点:如果是,获得锁;否则监听前一个节点的删除事件。
.NE
T 生态中,StackExchange.Redis 和 Curator(需通过 IKVM 或 .NET Core 兼容层)或 ZooKeeperNetEx 是主流选择。二者 API 抽象层级完全不同:
TryAcquire(string key, string value, int expiryMs) 和 Release(string key, string value),核心是原子 Lua 脚本调用InterProcessMutex 类,内部处理重试、Watch 回调、会话重建等,使用者只需 mutex.Acquire() / mutex.Release()
Acquire(timeout) 控制,但超时判定依赖 ZK 会话超时(sessionTimeout),不是应用层计时
// Redis 锁释放 Lua 脚本示例(C# 中通过 Eval 执行)
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end
如果业务能容忍秒级锁失效(如定时任务去重),Redis 更轻量、吞吐高;如果涉及资金、库存等强一致性场景,且已有 ZK 基础设施,ZK 的可靠性更可预期。
别忽略部署环境:K8s 里跑 ZK 集群的 Pod 重启、滚动更新、网络分区都会影响会话稳定性;而 Redis 在云上托管服务(如 Azure Cache for Redis)已内置高可用,但得确认其是否支持 WAIT 命令保障写入多数节点。
最容易被跳过的点是锁的粒度——用同一个 key 锁住所有订单 vs 按 order_id 分锁,后者才能真正并发,前者只是串行化。