分布式锁实战演练:跨越 JVM 的并发掌控者

发布时间:2026/7/9 18:51:55

分布式锁实战演练:跨越 JVM 的并发掌控者 前言为什么synchronized突然不香了前几篇博客我们把synchronized和ReentrantLock这个级别的锁研究得透透的了。但在如今微服务、集群化部署的大时代下这些传统的锁突然“失灵”了。为什么因为synchronized和ReentrantLock都是单机锁本地锁它们的作用域只能是在同一个 JVM 进程内部想象一下搞秒杀活动由于流量太大你部署了 3 台 Tomcat 服务器处理订单。此时一件商品同时被 3 个人抢由于是三个独立运行的机器本地锁根本拦不住跨服务器的请求结果就是商品发生了超卖。**为了解决跨 JVM 的锁问题“分布式锁”应运而生**相当于在三台机器外面挂出一把公共的大锁谁抢到谁才能进一、 打怪升级Redis 实现分布式锁的演进史Redis 是实现分布式锁最常见的组件因为它的速度极快而且支持单线程操作。但想用好Redis分布式锁里面全是坑我们看看前人是怎么踩坑的。1. 青铜级占坑法 (setnx)思路利用 Redis 的setnxSET if Not eXists命令。如果一个 key 不存在我就把它设置进去抢到锁如果已经存在我就抢锁失败。处理完业务再把它del释放锁。致命漏洞如果拿到锁的机器突然停电宕机了没来得及执行del操作。这把锁就永远留在了 Redis 里。其他人都饿死在门外——这就是死锁2. 白银级给锁加个寿命 (setnxexpire)思路为了防止宕机死锁我抢到锁之后立马给它加个过期时间比如 10 秒。哪怕我宕机了10 秒后 Redis 也会自动删掉它。致命漏洞这两步不是原子操作万一我刚执行完setnx还没来得及执行expire就宕机了怎么办死锁依然存在3. 黄金级原子占坑 (set key value EX 10 NX)思路从 Redis 2.6.12 开始官方支持吧setnx和设置过期时间合并为一条原子命令致命漏洞超时问题与误删。锁只有 10 秒但我业务执行了 15 秒这时候第 10 秒锁过期了别的机器把锁抢走了。并发安全没了等我 15 秒办完业务我习惯性地去del操作。结果我竟然把刚刚别人加的锁给删掉了4. 王者级终极形态 —— Redisson 看门狗机制 (Watch Dog)为了彻底解决“锁过期但业务还没跑完”的千古难题开源框架Redisson大显神威它自带了一只**“看门狗”**Redisson 帮你在后台开启一个守护线程。当你拿到锁时默认它只有 30 秒的寿命。但是看门狗每隔 10 秒会去看一眼主人你还在干活吗如果还在干活它就自动帮你发送一条续期命令把锁重新续满到 30 秒只要你不死看门狗会一直帮你续命由于宕机会导致看门狗也一并死掉所以根本不怕死锁二、 代码实战Redisson 秒杀分布式锁完整演示引入 Redisson 极其简单下面就是生产级环境里我们真正在用的写法!-- 引入 Redisson 依赖 --dependencygroupIdorg.redisson/groupIdartifactIdredisson-spring-boot-starter/artifactIdversion3.17.4/version/dependencyimportorg.redisson.api.RLock;importorg.redisson.api.RedissonClient;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importjava.util.concurrent.TimeUnit;ServicepublicclassSeckillService{// 注入强大的 Redisson 客户端AutowiredprivateRedissonClientredissonClient;publicvoidbuyIphone(){// 1. 获取一把分布式锁只要名字一样就是同一把大锁RLocklockredissonClient.getLock(seckill:iphone14:lock);// 2. 加锁阻塞等待核心绝招不要手动传过期时间让看门狗自动生效lock.lock();try{System.out.println(Thread.currentThread().getName() - 成功抢到了锁开始疯狂处理秒杀核心业务...);// 模拟极其耗时的业务比如 40 秒看门狗会在后台帮我们不停续期确保锁不会失效Thread.sleep(40000);System.out.println(Thread.currentThread().getName() - 业务办完准备下班);}catch(InterruptedExceptione){e.printStackTrace();}finally{// 3. 终极防坑解锁前务必要判断这把锁是不是自己的 且 锁是不是还被锁着if(lock.isLocked()lock.isHeldByCurrentThread()){lock.unlock();System.out.println(Thread.currentThread().getName() - 解锁成功);}}}}【硬核细节剖析】如果你在使用lock.lock(10, TimeUnit.SECONDS)手动传了过期时间看门狗机制就会失效到期强行释放锁。只有使用无参的lock.lock()时Redisson 才会默认开启看门狗机制三、 面试必杀技Redis 分布式锁的缺陷 (高阶局)如果你仅仅答到看门狗面试官最多给你 80 分。想拿 100 分甚至震撼面试官一定要谈一谈 Redis 极少出现的“脑裂”或主从同步延迟带来的坑。面试官“如果你的锁刚刚写入了 Redis 主节点 (Master)主节点立刻宕机了从节点 (Slave) 还没来得及同步到这个锁就被推举为了新的主节点。这时候别的机器也能过来拿到这把锁。这就意味着有两台机器同时拿到锁并发全乱了。你怎么看”破局方案为了对抗极端情况Redis 的作者提出了RedLock红锁算法。核心思想搞 5 台完全独立的 Redis 主节点不上任何主从。每次加锁要分别去请求这 5 台 Redis。只有超过半数3台及以上都加锁成功了才算真的抢到锁虽然牛逼但这玩意儿重到令人发指。一般公司如果没有变态级的金融级强一致要求千万不要用 RedLock性能全被毁了。大多数情况下用普通的 Redisson 主从集群就已经完全够用了。总结从本地的synchronized跨越到微服务的 Redis 分布式锁是后端程序员脱胎换骨的必经之路。掌握了分布式环境的加锁原理、超时释放以及续命机制你在大型微服务架构面前就可以横着走了

相关新闻