news 2026/4/2 5:42:21

深入理解 Redisson 分布式锁

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入理解 Redisson 分布式锁

引言

在分布式系统中,多个服务实例往往需要同时访问同一共享资源,例如:

  • 多节点同时修改同一条库存记录
  • 并发执行同一订单处理流程
  • 多实例定时任务同时触发
  • 并发写入同一个数据对象

如果没有分布式锁机制做互斥控制,系统容易出现数据竞争、写冲突、脏写、重复执行等问题。
Redis 因为高性能、单线程执行模型、丰富的原子命令和 Lua 脚本支持,成为当前最主流的分布式锁实现底座。

而 Redisson 作为 Redis 官方推荐的 Java 客户端之一,在锁语义、可重入性、自动续期、原子性保障等方面具有较高的工程完备度。
本文将从工作原理到工程实践全面介绍 Redisson 分布式可重入锁(RLock)。


一、为什么选择 Redisson 实现分布式锁?

如果直接手写 Redis 分布式锁(例如使用SETNX+EXPIRE),会面临大量工程级问题:

问题原因典型风险
SETNX 与 EXPIRE 非原子两条命令获取锁后未设置过期时间 → 死锁
锁删除不安全业务线程崩溃 / 误删删除了别的线程的锁
锁超时后自动释放EX 过期时间不足业务未执行完 → 锁提前过期导致数据错误
不支持可重入SETNX 无法表达线程所有者同一线程再次加锁会造成自阻塞
缺乏自动续期机制自己实现困难业务执行长任务容易导致锁失效

Redisson 提供的 RLock 特性完整解决了上述问题:

  • 可重入语义
  • 自动续期(看门狗机制)
  • 原子加锁 / 解锁(Lua 脚本)
  • 多种锁模式(公平锁、联锁、红锁等)
  • 分布式环境稳定可靠

因此 Redisson 是 Java 体系中工程落地最完善的 Redis 分布式锁方案。


二、Redisson 分布式锁底层原理

1. 锁在 Redis 中的结构

Redisson 使用 Redis 的Hash结构保存锁元数据:

Key: myLock Type: Hash Field: <uuid:threadId> Value: <reentrant count> Expire: 30 seconds (默认锁自动过期时间)

示例:

HSET myLock "e8c0d-...-12:23" 1 EXPIRE myLock 30

这带来几个重要特性:

  • 支持可重入:同一线程再次加锁只需增加次数,不会阻塞
  • 线程级别锁所有权:clientId+threadId 作为唯一标识
  • Redis TTL 控制过期:防止死锁
  • Hash 支持多个 field,可扩展到联锁等高级场景

2. 加锁流程详解

加锁过程使用 Lua 脚本确保原子性:

核心流程(简化逻辑)

  1. 锁不存在→ 设置 Hash(field=当前线程)并设置 TTL
  2. 锁存在但属于当前线程→ 可重入次数+1
  3. 锁存在且不属于当前线程→ 阻塞等待或立即返回失败

所有分支均由 Lua 脚本完成,确保操作原子、不被打断。


三、Spring Boot + Redisson 配置示例

@ConfigurationpublicclassRedissonConfig{@BeanpublicRedissonClientredissonClient(){Configconfig=newConfig();config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(0);returnRedisson.create(config);}}

四、加锁与释放锁使用方法

Redisson 提供两类常用加锁方式:

  • lock.lock():阻塞式加锁,自动启动看门狗续期
  • lock.tryLock(...):可设定等待时间与租期,更灵活

1. 使用 lock() —— 自动续期(Watchdog)

@ServicepublicclassLockExampleService{@AutowiredprivateRedissonClientredissonClient;publicvoidtestLock(){RLocklock=redissonClient.getLock("order:lock");try{lock.lock();// 不指定时间 → 自动续期机制生效System.out.println("获取到锁,执行操作...");Thread.sleep(60000);// 业务耗时,看门狗续期保障锁有效}catch(Exceptione){e.printStackTrace();}finally{if(lock.isHeldByCurrentThread()){lock.unlock();}}}}

特点:

  • 默认锁过期时间:30 秒
  • 自动续期(看门狗)每 10 秒刷新过期时间

2. 使用 tryLock()

publicvoidtryLockExample(){RLocklock=redissonClient.getLock("product:lock");try{if(lock.tryLock(5,TimeUnit.SECONDS)){System.out.println("成功获取锁");Thread.sleep(30000);}else{System.out.println("未获取到锁");}}catch(Exceptione){e.printStackTrace();}finally{if(lock.isHeldByCurrentThread()){lock.unlock();}}}

特点:

  • 5 秒内阻塞等待
  • 拿到锁后:启用看门狗自动续期

五、看门狗(Watchdog)机制完整解析

1. 看门狗的工作机制

默认:

  • 检查周期:10 秒
  • 每次续期:将锁 TTL 重置为 30 秒

工作流程:

  1. 定时任务触发
  2. 判断锁是否仍被当前线程持有
  3. 若是 → 调用PEXPIRE myLock 30000
  4. 若线程结束或锁已释放 → 停止续期

2. 为什么需要续期?

如果业务耗时超过锁 TTL(30s),传统分布式锁会提前失效,导致并发问题。
续期确保业务执行再长,也不会中途释放锁。

3. 如何判断“锁属于当前线程”?

通过检查:

HEXISTS myLock <clientId:threadId>

只要当前线程还是 lock 的 owner,就继续续期。


六、Redis 中锁的实时具象表现

加锁后执行:

HGETALL order:lock TTL order:lock

可能看到:

1) "7ab1e9...:23" 2) "1" (integer) 30

随着看门狗执行,TTL 会保持波动但始终在 30 秒附近。


七、锁释放原理(Lua 脚本)

Redisson 使用 Lua 保证解锁的原子性。

  1. 检查锁是否属于当前线程
  2. 若重入次数 > 1 → 次数 -1
  3. 若重入次数为 1 → 删除整个 key
  4. 若锁不属于当前线程 → 不执行任何操作(避免误删)

这个机制保证:“只有锁持有者才能释放锁”。


八、典型问题与常见误区(FAQ)

1. 调用 lock.lock(10, TimeUnit.SECONDS) 会启用看门狗吗?

不会。
指定租期时不启用看门狗,锁达到指定时间后自动释放。


2. 看门狗续期时间可以调整吗?

可以:

config.setLockWatchdogTimeout(45000);// 默认30s

3. Redisson 如何避免死锁?

  • 线程异常退出 → 看门狗停止续期
  • 默认 30s TTL 自动过期
  • 锁结构中包含线程标识,避免误删

4. 可重入锁意味着什么?

同一个线程可以多次获取该锁,不会进入自阻塞:

lock.lock(); lock.lock(); // 重入,计数+1

5. 可否用于分布式事务?

可以用于分布式资源互斥,但不能代替事务。


十、完整业务案例:库存扣减(典型高并发场景)

@ServicepublicclassStockService{@AutowiredprivateRedissonClientredissonClient;publicvoiddeductStock(){RLocklock=redissonClient.getLock("stock:lock");try{lock.lock();// 触发看门狗续期System.out.println("开始扣减库存...");// 模拟扣减操作Thread.sleep(30000);}catch(Exceptione){e.printStackTrace();}finally{if(lock.isHeldByCurrentThread()){lock.unlock();}}}}

适用于:

  • 秒杀减库存
  • 订单去重
  • 并发任务幂等控制
  • 分布式调度系统

总结:Redisson 是 Java 开发中最成熟的 Redis 分布式锁实现

功能点Redisson 是否支持说明
可重入分布式锁Hash 结构记录重入次数
自动续期(看门狗)lock() 自动启用
原子加锁与解锁Lua 脚本保障原子性
死锁自动恢复TTL 到期自动释放
公平锁、联锁、读写锁丰富的分布式同步结构
高性能、可伸缩基于 Redis 单线程执行模型

凭借其完善的锁语义、自动续期机制与 Lua 原子操作设计,Redisson 是 Java 生态中分布式锁的首选方案,适用于中大型业务中的强一致性场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!