Redis分布式锁,多种类型随心选,解锁高效并发新体验

文章导读
用Redis实现分布式锁最直接的方式就是用SET命令加NX和PX参数,比如 set key mylock NX PX 30000,这就给key上锁30秒。
📋 目录
  1. Redis分布式锁,多种类型随心选,解锁高效并发新体验
  2. 为啥需要分布式锁?
  3. 不同场景不同选择
  4. 实战经验分享
  5. 避坑指南
  6. 简单实现示例
  7. 常见问题FAQ
  8. 引用来源
A A

Redis分布式锁,多种类型随心选,解锁高效并发新体验

用Redis实现分布式锁最直接的方式就是用SET命令加NX和PX参数,比如 set key mylock NX PX 30000,这就给key上锁30秒。

为啥需要分布式锁?

现在很多系统都是好几台机器一起跑,比如你有个秒杀活动,很多用户同时来抢一件商品。如果没锁控制,可能最后商品库存会变成负数,因为每台机器都以为还有货。分布式锁就是让大家在抢资源时排个队,谁先拿到锁谁先操作,保证了数据不会乱。

不同场景不同选择

最简单的就是刚才说的用SET NX PX,但很多时候这还不够。比如你有个任务要执行很长时间,30秒锁自动过期了,任务还没做完,别人就能拿到锁,这就出问题了。这时候可以用Redisson框架的看门狗机制,它会自动检查,如果任务还在跑,就给锁续期。

还有些情况,多个资源要按顺序加锁,不然可能死锁。Redisson提供了联锁,可以把多个锁绑在一起,要拿一起拿,要放一起放,避免死锁发生。

如果你想要更细粒度的控制,比如读写分离,可以用读写锁。读的时候可以很多人一起读,但写的时候只能一个人写,这样效率更高。Redisson的RReadWriteLock就能做到。

甚至你还可以用信号量,控制同时有多少个线程能访问某个资源,比如只允许10个用户同时下载一个大文件。

实战经验分享

我做过一个订单处理系统,高峰期同时来很多订单。最开始用简单的SET NX,结果老出问题,有的订单被处理了两次。后来改用Redisson的可重入锁,同一个线程可以多次加锁,配合看门狗,稳定多了。关键代码就几行:RLock lock = redisson.getLock("orderLock"); lock.lock(); try { // 处理订单 } finally { lock.unlock(); }

还有一次做库存扣减,用了读写锁。查询库存的时候用读锁,很多人可以同时查;实际扣减的时候用写锁,保证安全。这样既保证了数据正确,查询速度也快。

避坑指南

用分布式锁有几个容易掉坑的地方。第一,锁一定要设置过期时间,不然万一程序崩溃,锁永远不释放,整个系统就卡死了。第二,解锁的时候要检查是不是自己的锁,不能把别人的锁解了。可以用UUID当value,解锁前先比对一下。第三,网络可能不稳定,命令执行了但没收到回复,这时候要小心处理,最好有重试机制。

Redis分布式锁,多种类型随心选,解锁高效并发新体验

简单实现示例

如果你不想用Redisson,可以自己写个简单的。核心就是SET NX PX,加唯一ID,配合Lua脚本保证原子性。Lua脚本很重要,因为解锁需要先检查再删除,如果不是原子操作,可能检查完锁还是自己的,删除的时候锁已经过期被别人拿走了。

常见问题FAQ

问:Redis分布式锁在集群环境下安全吗?

答:在Redis集群下,如果主节点设置了锁然后挂了,锁可能还没同步到从节点,这时候新主节点可能没这个锁,会导致锁失效。可以用Redlock算法,但比较复杂,一般场景用单Redis加故障转移也够用。

问:锁的过期时间设置多长合适?

答:这要看你的业务操作需要多长时间。一般设置成平均操作时间的2-3倍。如果操作时间变化很大,可以用看门狗机制自动续期,避免锁过早释放。

问:除了Redis,还有别的分布式锁实现吗?

答:有,比如用ZooKeeper、Etcd或者数据库。Redis性能好,用起来简单;ZooKeeper更可靠,但性能差些。根据你的业务需求选最合适的。

引用来源

本文内容参考了Redis官方文档关于SET命令和分布式锁的说明,Redisson开源框架的官方文档和示例代码,以及《Redis设计与实现》一书中关于分布式系统的讨论。部分实战经验来自作者在电商和金融项目中的实际应用。