《锁得住,才能活得久》——一篇讲透 Redisson 分布式锁的技术实录

------来自一位被死锁坑哭后发誓要掌控全局的程序员的灵魂写作


一、💣💣💣 为啥不用 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,心里才稳当。

相关推荐
雾林小妖3 分钟前
springboot集成deepseek
java·spring boot·后端
愿你天黑有灯下雨有伞42 分钟前
枚举策略模式实战:优雅消除支付场景的if-else
java·开发语言·策略模式
Dcs1 小时前
gRPC性能陷阱:低延迟网络下的客户端瓶颈揭秘
java
探索java1 小时前
深入解析 Spring 获取 XML 验证模式的过程
xml·java·spring
找不到、了1 小时前
Java设计模式之<装饰器模式>
java·设计模式·装饰器模式
java叶新东老师2 小时前
解决windows系统下 idea、CLion 控制台中文乱码问题
java·windows·intellij-idea
岁忧2 小时前
(LeetCode 面试经典 150 题 ) 155. 最小栈 (栈)
java·c++·算法·leetcode·面试·go
yourkin6662 小时前
为什么现在 Spring Boot 默认使用 CGLIB 了?
java·开发语言·jvm
这就是佬们吗3 小时前
初识 docker [上]
java·开发语言·笔记·docker·容器
阿华的代码王国3 小时前
【Android】卡片式布局 && 滚动容器ScrollView
android·xml·java·前端·后端·卡片布局·滚动容器