news 2026/4/15 10:43:22

Redisson分布式锁:从入门到实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redisson分布式锁:从入门到实战

一、为什么需要分布式锁?

在单体应用中,我们使用Java的synchronized或ReentrantLock就能解决并发问题。但在微服务架构下,多个实例同时运行,单机的锁机制就失效了。这时就需要分布式锁来保证跨JVM的互斥访问。

分布式锁的核心需求

  1. 互斥性:同一时刻只能有一个客户端持有锁
  2. 防止死锁:客户端崩溃后能自动释放锁
  3. 容错性:Redis节点故障时仍能正常工作
  4. 可重入性:同一个线程可以多次获取同一个锁

二、Redis实现分布式锁的基础方案

2.1 最简单的实现:SET NX

最早期的实现方式是使用SET命令的NX选项:

SET key value NX PX 30000
  • NX:只在key不存在时设置
  • PX:设置过期时间(毫秒)

这种方式的缺点:

  • 无法实现可重入锁
  • 无法获取锁的持有人信息
  • 无法实现锁的自动续期

2.2 完整实现方案

一个相对完善的Redis分布式锁实现需要包含以下逻辑:

Redis分布式锁基础架构

  1. 加锁:SET key value NX PX timeout
  2. 解锁:Lua脚本保证原子性
  3. 看门狗:定时续期防止业务执行时间超过锁过期时间

三、Redisson分布式锁

Redisson是Redis的Java客户端,它提供了完善的分布式锁实现,解决了原生Redis锁的各种问题。

3.1 核心特性

  1. 可重入锁:同一个线程可多次获取锁
  2. 公平锁:按请求顺序获取锁
  3. 读写锁:允许多个读操作或单个写操作
  4. 红锁:跨多个Redis节点的分布式锁
  5. 自动续期:看门狗机制自动延长锁时间
  6. 锁释放:Lua脚本保证原子性操作

3.2 基本使用

// 获取锁对象 RLock lock = redisson.getLock("myLock"); try { // 加锁(支持等待时间和自动续期) boolean locked = lock.tryLock(100, 30000, TimeUnit.MILLISECONDS); if (locked) { // 执行业务逻辑 doBusiness(); } } finally { // 释放锁 if (lock.isHeldByCurrentThread()) { lock.unlock(); } }

四、Redis实现 vs Redisson对比

Redis实现 vs Redisson对比

特性Redis原生实现Redisson
实现复杂度高,需要处理多种边界情况低,开箱即用
可重入锁需要自己实现原生支持
自动续期需要后台线程续期看门狗自动续期
公平锁难以实现开箱即用
读写锁难以实现开箱即用
红锁需要自己协调开箱即用
异常处理需要仔细处理完善的异常体系

结论:生产环境推荐使用Redisson,它已经处理了各种边界情况和异常场景。

五、Redisson核心原理解析

5.1 加锁机制

Redisson使用Lua脚本保证加锁的原子性:

Redisson加解锁流程

-- 检查key是否存在 if redis.call('exists', KEYS[1]) == 0 then -- 不存在则设置,使用hash结构存储 redis.call('hset', KEYS[1], ARGV[2], 1) redis.call('pexpire', KEYS[1], ARGV[1]) return nil end -- key已存在,检查是否是当前线程 if redis.call('hexists', KEYS[1], ARGV[2]) == 1 then -- 是当前线程,增加重入次数 redis.call('hincrby', KEYS[1], ARGV[2], 1) redis.call('pexpire', KEYS[1], ARGV[1]) return nil end return redis.call('pttl', KEYS[1])

锁的数据结构使用Hash类型:

  • Key:锁名称
  • Field:线程标识(UUID:threadId)
  • Value:重入次数

5.2 看门狗机制

看门狗(Watchdog)是Redisson的核心特性,用于解决锁超时问题:

Watchdog机制

  1. 业务获得锁时,启动后台定时任务
  2. 每隔lockWatchdogTimeout/3时间检查锁是否还持有
  3. 如果还持有则重置过期时间
  4. 业务释放锁时停止看门狗

默认情况下,看门狗每10秒续期一次,锁的过期时间为30秒。

5.3 解锁机制

解锁同样使用Lua脚本保证原子性:

-- 检查锁是否是当前线程持有 if redis.call('hexists', KEYS[1], ARGV[2]) <= 0 then return nil end -- 减少重入次数 local counter = redis.call('hincrby', KEYS[1], ARGV[2], -1) -- 如果重入次数大于0,重置过期时间 if counter > 0 then redis.call('pexpire', KEYS[1], ARGV[1]) return 0 end -- 重入次数为0,删除锁 redis.call('del', KEYS[1]) -- 发布解锁消息 redis.call('publish', KEYS[2], ARGV[3]) return 1

六、生产环境实战案例

生产环境实战案例

6.1 库存扣减

@Service public class InventoryService { @Autowired private RedissonClient redisson; public boolean deductStock(String productId, int quantity) { RLock lock = redisson.getLock("stock:" + productId); try { // 等待5秒,锁过期30秒 if (lock.tryLock(5, 30, TimeUnit.SECONDS)) { // 查询库存 int stock = getStock(productId); if (stock >= quantity) { // 扣减库存 updateStock(productId, stock - quantity); return true; } return false; } throw new BusinessException("系统繁忙,请稍后重试"); } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } }

6.2 订单幂等性控制

@Service public class OrderService { @Autowired private RedissonClient redisson; public Order createOrder(OrderRequest request) { String lockKey = "order:create:" + request.getUserId(); RLock lock = redisson.getLock(lockKey); try { if (lock.tryLock(3, 10, TimeUnit.SECONDS)) { // 检查是否已有未完成订单 Order existOrder = getUnfinishedOrder(request.getUserId()); if (existOrder != null) { return existOrder; } // 创建新订单 Order order = buildOrder(request); saveOrder(order); return order; } throw new BusinessException("操作频繁,请稍后重试"); } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } }

6.3 定时任务防止重复执行

@Component public class DataSyncJob { @Autowired private RedissonClient redisson; @Scheduled(cron = "0 */5 * * * *") public void syncData() { String lockKey = "job:data:sync"; RLock lock = redisson.getLock(lockKey); try { // 尝试获取锁,不等待 if (lock.tryLock(0, TimeUnit.SECONDS)) { // 执行数据同步 doSync(); } else { log.info("上次同步任务尚未完成,跳过本次执行"); } } finally { if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } }

七、高级特性:读写锁

在读多写少的场景下,使用读写锁可以大幅提升并发性能:

读写锁原理

@Service public class ConfigService { @Autowired private RedissonClient redisson; public String getConfig(String key) { RReadWriteLock rwLock = redisson.getReadWriteLock("config:" + key); RLock readLock = rwLock.readLock(); try { readLock.lock(); // 多个线程可以同时读取 return queryFromDB(key); } finally { readLock.unlock(); } } public void updateConfig(String key, String value) { RReadWriteLock rwLock = redisson.getReadWriteLock("config:" + key); RLock writeLock = rwLock.writeLock(); try { // 写操作独占锁 writeLock.lock(); updateDB(key, value); // 清除缓存 clearCache(key); } finally { writeLock.unlock(); } } }

八、最佳实践

8.1 锁的粒度选择

  1. 粗粒度:锁整个表或模块,简单但并发度低
  2. 细粒度:锁单个记录,并发度高但实现复杂

推荐:根据业务场景选择合适的粒度,库存扣减用商品维度,订单创建用用户维度。

8.2 锁的过期时间设置

  1. 不要设置过短,避免业务未执行完就释放
  2. 不要设置过长,避免故障时长时间阻塞
  3. Redisson的看门狗会自动续期,但要设置合理的初始时间

推荐:根据业务执行时间的P99值设置,预留50%余量。

8.3 异常处理

  1. 捕获中断异常,确保锁能被释放
  2. 使用tryLock而不是lock,避免无限等待
  3. 检查锁的持有状态,避免误释放

九、常见问题

Q1:Redisson锁会丢失吗?

不会。Redisson使用看门狗机制,即使业务执行时间超过锁的过期时间,也会自动续期,直到业务主动释放锁。

Q2:Redis主从切换会影响锁吗?

会。单节点Redis在主从切换时可能丢失锁。需要使用Redisson的红锁(RedLock)或Redis Cluster。

Q3:如何实现公平锁?

Redisson提供了公平锁实现:

RLock fairLock = redisson.getFairLock("myFairLock"); fairLock.lock();

Q4:性能如何?

Redisson的分布式锁性能很好,单机QPS可达5万+,足以应对大多数场景。如有更高性能需求,可以考虑分段锁或本地锁+分布式锁的组合方案。

十、总结

Redisson分布式锁是Java领域最成熟的Redis分布式锁解决方案:

  1. 使用简单:API友好,学习成本低
  2. 功能完善:支持多种锁类型和场景
  3. 稳定可靠:经过大量生产环境验证
  4. 性能优异:看门狗机制和Lua脚本保证性能

在实际项目中,建议优先使用Redisson,它已经帮你处理了各种复杂的边界情况,让你专注于业务逻辑的实现。

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

核电站反应堆数字孪生 + 大模型:安全状态监测与风险预警技术

点赞、关注、收藏&#xff0c;不迷路 核电站反应堆作为核电装备的核心核心&#xff0c;是集高温高压、强放射性、多物理场耦合、运行工况复杂于一体的精密系统&#xff0c;其安全稳定运行直接关系到核电项目的生产安全与周边生态安全。传统反应堆安全状态监测与风险预警模式存在…

作者头像 李华
网站建设 2026/4/13 11:47:43

直流电机速度单闭环控制系统:Matlab/Simulink 仿真与实现

直流电机速度单闭环控制系统&#xff08;电机为传递函数建模&#xff09; matlab/simulink 仿真模型设计报告 在控制系统领域&#xff0c;直流电机的速度控制是一个经典且重要的课题。今天咱们就来讲讲基于传递函数建模的直流电机速度单闭环控制系统&#xff0c;并用 Matlab/S…

作者头像 李华
网站建设 2026/4/9 9:42:14

优化SEO效果的长尾关键词策略与应用分享

在优化SEO效果的长尾关键词策略中&#xff0c;内容概要扮演着引导读者理解的关键角色。通过对长尾关键词的分析与阐释&#xff0c;读者能够明确其重要性以及在实际应用中的具体策略。本段将概述长尾关键词如何在提高网站流量和排名方面发挥作用&#xff0c;并简要介绍选择与应用…

作者头像 李华
网站建设 2026/3/13 12:09:28

10410_基于Springboot的文化旅游宣传网站

1、项目包含项目源码、项目文档、数据库脚本、软件工具等资料&#xff1b;带你从零开始部署运行本套系统。2、项目介绍以甘南藏族自治州为例&#xff0c;其丰富的自然遗产与人文景观构成了独特的旅游生态体系&#xff0c;年接待游客量突破千万人次的背景下&#xff0c;旅游管理…

作者头像 李华
网站建设 2026/4/13 23:32:22

计算机毕业设计springboot高校师范生实习管理小程序 基于SpringBoot的高校师范生教育实习过程管理与协同平台 SpringBoot框架下的师范生教学实践移动化管理信息系统

计算机毕业设计springboot高校师范生实习管理小程序 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。 在教育数字化转型持续深化的背景下&#xff0c;师范生教育实习作为连接理论…

作者头像 李华