JAVA常用分布式锁Redisson详解

 更新时间:2025年05月16日 10:41:52   作者:时光呢  
Redisson分布式锁通过Lua脚本的原子性、可重入设计、Watchdog 自动续期和Pub/Sub 通知机制,实现了高效的分布式锁管理,本文给大家介绍JAVA常用分布式锁Redisson详解,感兴趣的朋友一起看看吧

1. 加锁过程

底层命令与数据结构

  • Redis 数据结构:使用 Hash 结构存储锁信息,Key 为锁名称,Field 为客户端唯一标识(如 UUID + 线程ID),Value 为锁的重入次数。
  • Lua 脚本原子性:通过 Lua 脚本在 Redis 中原子性执行加锁逻辑:
 
if (redis.call('exists', KEYS[1]) == 0) then
    redis.call('hincrby', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
end;
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]);
  • 若锁不存在(exists 为 0)或属于当前线程(hexists 为 1),则增加重入次数并刷新过期时间。
  • 若锁被其他线程占用,返回锁的剩余生存时间(TTL)。

可重入性

同一线程多次获取锁时,重入次数递增,确保不会因多次加锁导致死锁。

2. 锁自动续期(Watchdog 机制)

  • 后台线程续期:加锁成功后,启动一个 Watchdog 线程(看门狗),定期(默认每 10 秒)检查锁是否仍被持有。
  • 续期条件:仅当客户端仍持有锁且业务未完成时,通过 pexpire 命令将锁的过期时间重置为初始值(默认 30 秒)。
  • 崩溃容错:若客户端崩溃,Watchdog 线程停止,锁最终因过期自动释放,避免死锁。

3. 释放锁

释放逻辑

Lua 脚本原子释放

if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then
    return nil;
end;
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
if (counter > 0) then
    redis.call('pexpire', KEYS[1], ARGV[2]);
    return 0;
else
    redis.call('del', KEYS[1]);
    redis.call('publish', KEYS[2], ARGV[1]);
    return 1;
end;
return nil;
  • 减少重入次数,若次数归零则删除锁,并通过 Pub/Sub 通知等待线程。
  • 确保只有锁的持有者能释放锁,避免误删。

4. 锁竞争与等待

  • 自旋重试:若锁被占用,客户端进入循环,间隔性尝试加锁。
  • Pub/Sub 订阅通知:通过订阅锁释放事件(redisChannel),避免频繁轮询。当锁释放时,Redis 发布消息通知等待线程竞争锁,减少无效请求。

5. 高可用与容错 Redis 部署模式

  • 单节点模式:简单但存在单点故障风险。
  • 主从/集群模式:使用 RedissonMultiLock 实现 RedLock 算法(需多个独立 Redis 节点):
    • 向所有节点顺序申请锁。
    • 当多数节点加锁成功且总耗时小于锁超时时间时,认为加锁成功。
    • 规避主从切换导致锁丢失的问题,但需权衡性能和一致性。

6. 关键注意事项

  • 业务执行时间:业务逻辑必须在锁的过期时间内完成,否则锁可能提前释放。
  • 时钟同步问题:在 RedLock 中,若 Redis 节点间时钟不同步,可能导致锁失效。
  • 网络延迟:极端情况下,锁可能被多个客户端同时持有(需结合业务幂等性处理)。

总结

  • Redisson 分布式锁通过 Lua 脚本的原子性可重入设计Watchdog 自动续期和 Pub/Sub 通知机制,实现了高效的分布式锁管理。其核心优势在于:
  • 避免误删锁(仅持有者可释放)。
  • 支持可重入,适应复杂业务逻辑。
  • 自动续期防止业务未完成时锁过期。
  • 通过 RedLock 支持高可用场景,但需谨慎权衡一致性与性能。

到此这篇关于JAVA常用分布式锁Redisson的文章就介绍到这了,更多相关java分布式锁redisson内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用IDEA向Gitee提交SpringBoot项目进行远程管理

    使用IDEA向Gitee提交SpringBoot项目进行远程管理

    本文主要介绍了使用IDEA向Gitee提交SpringBoot项目进行远程管理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • 一个Servlet是如何处理多个请求的?

    一个Servlet是如何处理多个请求的?

    以前我一直以为一个Servlet只能处理一个请求,后来发现是自己太菜了,可以借助携带一个参数来完成多个请求的处理,根据参数的不同,在核心的service方法中调用不同的业务方法,来实现处理多个servlet请求的目的,废话不多说,直接上代码,需要的朋友可以参考下
    2021-06-06
  • Java代码实现矩形覆盖实例

    Java代码实现矩形覆盖实例

    这篇文章主要介绍了Java代码实现矩形覆盖实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,,需要的朋友可以参考下
    2019-06-06
  • 盘点SpringBoot中@Async注解的遇到的坑点及解决办法

    盘点SpringBoot中@Async注解的遇到的坑点及解决办法

    SpringBoot是一个流行的Java开发框架,在异步编程方面,Spring Boot提供了@Async注解,它能够让方法异步执行,然而,在使用@Async注解时,有一些潜在的坑需要注意,本文将深入探讨Spring Boot中使用@Async注解时可能遇到的8大坑点,并提供相应的解决方案
    2024-03-03
  • 详解java 客户端链接不上redis解决方案

    详解java 客户端链接不上redis解决方案

    这篇文章主要介绍了详解java 客户端链接不上redis解决方案,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-01-01
  • Java中时间戳和时间的转换方法代码

    Java中时间戳和时间的转换方法代码

    这篇文章主要介绍了Java中时间戳和时间的转换的相关资料,Java8中时间戳与日期时间对象之间的转换是编程中常见的操作,通过时间字符串获取时间对象也是其中的一种方法,需要的朋友可以参考下
    2025-03-03
  • java虚拟机

    java虚拟机

    2008-01-01
  • 运行java的class文件方法详解

    运行java的class文件方法详解

    这篇文章主要详细介绍了运行java的class文件方法的相关资料,需要的朋友可以参考下
    2015-02-02
  • Java线程休眠的5种方法

    Java线程休眠的5种方法

    这篇文章主要介绍了Java线程休眠的5种方法,分别是Thread.sleep、TimeUnit、wait、Condition、LockSupport,下面文章将对这五种方法进行详细讲解,需要的小伙伴可以参考一下
    2022-05-05
  • IntelliJ IDEA 好用插件之analyze inspect code详解

    IntelliJ IDEA 好用插件之analyze inspect code详解

    这篇文章主要介绍了IntelliJ IDEA 好用插件之analyze inspect code的相关知识,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-12-12

最新评论