Redis分布式锁的核心机制是使用SETNX命令实现互斥加锁:客户端通过SET key value NX PX 30000原子性地设置锁键值对,如果键不存在则成功加锁(NX),并设置30秒过期时间(PX)防止死锁。释放锁时,使用Lua脚本原子判断value匹配后删除键,确保只有锁持有者能解锁。Redlock算法通过多个独立Redis节点多数派(N/2+1)加锁提升可靠性,避免单点故障。
SETNX加锁详解
SETNX key value 命令,只有当key不存在时才设置value并返回1,否则返回0,这就是分布式锁的基本加锁原理。为了防止业务执行时间过长导致锁无法释放,我们需要给锁设置一个合理的过期时间,比如使用expire命令,但SETNX和EXPIRE不是原子操作,可能在setnx成功后宕机导致无过期时间,所以最佳实践是用SET key value NX PX 30000一次性设置。
释放锁的Lua脚本
释放锁不能简单del key,因为可能误删他人锁。使用Lua脚本:if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end。这样原子性保证了get和del的同时性,只有value匹配的持有者才能删除锁。
Redlock算法多节点实现
Redlock是Redis官方推荐的分布式锁算法。步骤:1. 在N个独立Redis节点上依次尝试加锁;2. 只要在多数节点(N/2+1)成功加锁就算获取锁成功;3. 加锁时间要短,包含网络延迟;4. 释放时在所有节点释放。解决了单节点故障问题,提高了锁的安全性和可用性。
锁自动续期机制
业务执行时间不确定时,用后台线程每10秒检查锁一次,如果还持有则续期(重新设置过期时间)。Redisson框架内置此机制,通过Redis的keyevent事件或定时任务实现,避免锁因长时间持有而过期导致并发问题。
常见问题与解决方案
问题1:时钟漂移。解决方案:使用相对时间计算TTL,避免NTP同步问题。问题2:网络分区。Redlock多数派机制确保一致性。问题3:锁超时过短。调大TTL并结合续期。问题4:性能瓶颈。多节点并行加锁优化。
FAQ
Q: Redis分布式锁为什么需要过期时间?
A: 防止服务宕机后锁永久持有,导致其他客户端无法获取锁。
Q: SETNX和SET NX有什么区别?
A: SETNX是旧命令,现在推荐SET key value NX PX ttl新语法,更原子。
Q: Redlock比单节点锁可靠吗?
A: 是,因为需要多数节点同意,容忍少数节点故障。
Q: 如何实现锁续期?
A: 开启守护线程,持有锁时每TTL/3续期一次。