------来自一位被死锁坑哭后发誓要掌控全局的程序员的灵魂写作
一、💣💣💣 为啥不用 RedisTemplate 来搞锁?
你是不是也干过这种事儿:
ini
Boolean success = redisTemplate.opsForValue().setIfAbsent("lockKey", "anyVal", 10, TimeUnit.SECONDS);
再加上 delete("lockKey")
释放锁,看上去人畜无害、灵活轻便。
但它有三个致命问题:
❌ 问题 1:线程挂了,锁永远不释放?
忘记加过期时间,锁变成僵尸锁,谁都抢不走,业务直接卡死。
❌ 问题 2:释放锁误删别人的锁!
线程 A 加锁,过期前刚好线程 B 重复拿到锁,
结果线程 A 还在 finally
里执行了 delete("lockKey")
------
恭喜你,B 的锁被误删,相当于别人家刚换门锁,你拿着老钥匙又打开了!
❌ 问题 3:没有重入性、没有阻塞等待、没有续期机制!
你要想支持:
- 自动续期(像看门狗那样)❌
- 阻塞等待一会再试 ❌
- 公平锁 ❌
- 锁续命 ❌
- 可重入锁 ❌
- tryLock 等待+租期 ❌
基本上就是个"山寨锁",功能少得可怜。
❌ 问题 4:不支持 RedLock / 多节点一致性
你用 RedisTemplate 时,是不具备多 Redis 节点下的锁一致性方案的(比如云 Redis 异地多活、主从切换等),一出故障就"锁飞了"。
✅ 所以 ------ 用 Redisson 的理由就呼之欲出了!
Redisson 做到了:
- 分布式安全性;
- 可重入 / 可中断;
- 看门狗续期机制;
- 公平锁 / 异步锁 / 读写锁等丰富锁模型;
- 天然支持 Spring Boot 与注解式加锁 (
@RedissonLock
插件还有人封装); - 源码成熟、功能完备、开箱即用
一切你想要的,Redisson 都有,
一切你不想处理的,Redisson 替你兜底。
好了,我们正式开启 Redisson 世界的奇幻冒险之旅 🧙♂️👇
🐕 二、Redisson 的"看门狗"机制:程序员的贴身保镖
Redisson 的锁有个神奇的地方:你只管加锁,逻辑没处理完,它会自动帮你续命。
🔦 默认行为:
- 使用
lock()
加锁时,Redisson 会启动一个后台线程; - 每 10 秒续一次命;
- 每次把锁的过期时间续到 30 秒;
- 只要你线程活着,它就一直守着锁。
这就像你不小心把车停在了限时 30 分钟的车位上,看门狗每 10 分钟帮你喂个硬币进去续费......直到你走。
只要逻辑未处理完,每隔10秒,续命30秒,无限重复
🕓 三、我能不能说"不用看门狗"?当然能!
Redisson 不是你丈母娘,它不会一直管着你。
如果你使用如下方式:
csharp
lock.lock(5, TimeUnit.SECONDS); // 锁 5 秒,不续期
或者:
csharp
lock.tryLock(3, 5, TimeUnit.SECONDS); // 最多等3秒,加锁后锁5秒
你就相当于告诉 Redisson:别续了,我知道自己几斤几两。
🧱 四、lock vs tryLock vs unlock,谁是核心戏骨?
方法 | 特点 | 适合场景 |
---|---|---|
lock() |
阻塞等待,拿不到锁就等下去 | 一定要拿到锁的业务 |
lock(time, unit) |
阻塞,但限定持有时间(关闭看门狗) | 执行时间可控的业务 |
tryLock() |
不等!拿不到锁立刻走 | 高并发快速失败场景 |
tryLock(wait, lease, unit) |
等待一段时间,拿到后最多持有 lease 时间 | 推荐 ✅ |
unlock() |
主动释放锁(别忘了!不然看门狗续你一脸) | finally 里使用 |
⚠️ 小提醒:只有加锁成功的线程,才能 unlock()
。否则你会看到报错:IllegalMonitorStateException
,仿佛 Redisson 对你喊:"你谁啊?"
🍱 五、常用方法使用示例
csharp
RLock lock = redissonClient.getLock("myLock");
try {
if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
// 拿到锁后执行逻辑
} else {
// 没拿到锁,降级处理
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
🌱 六、Spring Boot 整合 Redisson 步骤(超简明)
1️⃣ 引入依赖
xml
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.24.3</version> <!-- 版本可根据需要调整 -->
</dependency>
2️⃣ 配置 application.yml
yaml
redisson:
config: |
singleServerConfig:
address: "redis://localhost:6379"
password: null
threads: 4
nettyThreads: 4
3️⃣ 注入使用
csharp
@Autowired
private RedissonClient redissonClient;
public void doSomething() {
RLock lock = redissonClient.getLock("taskLock");
lock.lock(); // or tryLock(...)
try {
// your biz logic
} finally {
lock.unlock();
}
}
🧠 七、还有哪些你没问但必须知道的关键知识点?
✅ 1. 可重入锁(ReentrantLock)
Redisson 的 RLock
是可重入的,同一个线程加锁多次不会被锁死!
csharp
lock.lock(); // 第一次
lock.lock(); // 第二次(也能拿到)
✅ 2. 公平锁 vs 非公平锁
- 默认是非公平锁(谁快谁上)
- 支持使用
getFairLock(...)
获取公平锁(按排队顺序)
✅ 3. 可中断锁
csharp
lock.lockInterruptibly();
可响应 Thread.interrupt()
中断信号,适合线程池控制下的安全退出。
✅ 4. 异步加锁(带 Async
后缀)
支持 tryLockAsync()
、unlockAsync()
等异步调用方式,适合响应式编程。
✅ 5. 分布式锁的 RedLock?慎用!
RedLock 要在多个 Redis 节点上都加锁才算成功,理论好,但实践中容错差,官方不建议在生产使用(尤其云 Redis 环境)!
🎯 八、结语:做分布式系统的你,要会用这把"云端锁"
程序员的成长,不止是能写 for 循环,还要敢用分布式锁;
Redisson,不是唯一的方案,却是可靠的朋友。
下次你再遇到并发、库存、定时任务、幂等性问题时,别忘了手握 Redisson,心里才稳当。