news 2026/4/23 14:08:09

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/23 9:55:26

UVa 148 Anagram Checker

题目分析 本题要求编写一个程序&#xff0c;从给定的字典中找出所有能够由指定短语中的字母重组而成的单词组合。输入分为两部分&#xff1a;首先是字典部分&#xff08;每行一个单词&#xff0c;按字母顺序排序&#xff09;&#xff0c;然后是需要检查的短语列表&#xff08;…

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

H595单个和级联扩展开发-实战开发教程

H595使用手册 1. 简介 74HC595是一款8位串行输入/并行输出的移位寄存器,具有锁存功能。本驱动程序实现了单个74HC595控制8个IO输出和4个74HC595级联控制32个IO输出的功能,通过串行通信方式控制多个并行输出。 2. 硬件连接 根据硬件引脚映射配置文档,H595的引脚连接如下:…

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

Xilinx 7 系列 CameraLink 收发器 IP 深度解析

关注、星标公众号&#xff0c;精彩内容每日送达来源&#xff1a;网络素材1. 概述本 IP 为 Xilinx 7 系列 FPGA 提供了一套完整的 CameraLink Base&#xff08;单链路&#xff09;7:1 串行收发方案&#xff0c;采用 SDR&#xff08;Single Data Rate&#xff09; 模式&#xff0…

作者头像 李华
网站建设 2026/4/18 7:58:24

好写作AI:当环境研究遇上AI,你的论文终于可以“上管全球变暖,下治社区垃圾分类”了

你的研究同时涉及卫星遥感大图和土壤微生物数据——宏观与微观在PPT里同框出现时&#xff0c;像极了学术版的“穿越大剧”。别慌&#xff0c;你的“跨尺度数据缝合师”已上线。 凌晨的实验室&#xff0c;你电脑同时开着&#xff1a;全球CO₂浓度模拟图、流域水文监测表、某湿地…

作者头像 李华