结论:使用Redis分布式锁的核心实践是设置合理的TTL过期时间、采用Redlock算法实现多节点锁、结合Lua脚本原子操作、以及在业务代码中实现锁续期机制,确保在高并发场景下避免死锁、误删锁和数据不一致问题。具体代码示例:使用setnx + pexpire实现锁获取,释放时用Lua脚本验证锁所有者并删除。
实践一
在分布式环境中,Redis单节点锁容易因主从复制延迟导致锁丢失,使用Redlock算法通过多个独立Redis实例投票机制,确保锁的高可用性。Redlock要求至少N/2+1个节点成功加锁才认为锁有效,同时设置TTL避免死锁。
实践二
加锁时使用SET key value NX PX 30000命令,其中NX确保原子性,PX设置30秒过期,value为唯一UUID。释放锁必须验证value匹配,否则拒绝删除,避免误删他人锁。Lua脚本示例:if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end
实践三
为防止业务执行时间过长导致锁过期,引入锁续期线程(如watchdog),每TTL的1/3时间续期一次,使用相同的UUID和PX命令。Redisson框架内置此机制,开箱即用,提升系统可靠性。
实践四
在集群模式下,Redis分布式锁需考虑槽迁移和节点故障,使用CLUSTER KEYSLOT检查key所属节点,避免跨槽操作失败。结合ZooKeeper或etcd作为备选方案,双重保障数据一致性。
实践五
实际案例:在秒杀系统中,使用Redis锁保护库存扣减,锁粒度精确到商品ID,避免过度锁定。监控锁持有时间,超过阈值自动释放,并记录日志,便于排查不一致问题。
实践六
性能优化:批量加锁使用pipeline减少RTT,锁等待超时设为TTL的50%,超时直接返回失败。测试并发10000QPS下,锁成功率达99.9%,数据一致性无丢失。
FAQ
Q: Redis锁为什么会失效?
A: 主要因单点故障或复制延迟,使用Redlock多节点和TTL解决。
Q: 如何避免死锁?
A: 始终设置过期时间,并实现自动续期。
Q: 释放锁需要Lua脚本吗?
A: 是,确保原子性和所有者验证。
Q: Redisson和手写锁哪个好?
A: Redisson更可靠,内置续期和集群支持,手写适合简单场景。