redisson实现分布式锁

devtools/2024/9/22 18:25:20/

文章目录

    • 什么是redisson?
      • 主要特点
      • 主要功能
      • 使用场景
      • 开发者友好
      • 总结
    • redisson实现分布式
      • 1. 添加依赖
      • 2. 配置 RedissonClient
      • 3. 获取并使用锁
      • 注意事项
    • 锁超时处理
      • 1. 自动超时设置
      • 2. 动态设置超时时间
      • 3. 监控锁的状态
      • 4. 使用可重入锁
      • 注意事项
    • 看门狗机制
      • 如何工作?
      • 实现细节
      • 示例代码
      • 注意事项

redisson_1">什么是redisson?

Redisson 是一个高性能的基于 Redis 的 Java 客户端库,它不仅提供了一个简单的 Redis 连接封装,而且还实现了多种高级功能,使得开发人员可以更容易地在应用程序中集成 Redis 的能力。以下是关于 Redisson 的详细介绍:

主要特点

  1. 高级功能支持:除了基本的 Redis 客户端功能外,Redisson 还提供了诸如分布式锁、信号量、队列、集合等多种高级数据结构和功能的支持,非常适合构建复杂的分布式系统。

  2. 易用性:Redisson 提供了一个简洁的 API,使得开发者可以方便地使用 Redis 的高级功能,而无需直接编写复杂的 Redis 命令序列。

  3. 性能优化:Redisson 设计时考虑了性能因素,使用了异步非阻塞的编程模型,可以显著提高应用程序的吞吐量。

  4. 容错性:Redisson 具有良好的容错机制,可以在 Redis 节点发生故障时自动恢复连接,并继续提供服务。

  5. 集群支持:Redisson 支持 Redis 单机、主从架构、哨兵架构以及 Redis Cluster 架构,可以适应不同的部署环境。

主要功能

  • 分布式:实现可重入锁、公平锁、读写锁等,可以有效防止分布式环境下的并发冲突。
  • 分布式集合:提供 Set、List、Map、BitSet 等常用数据结构的分布式实现。
  • 分布式队列:包括阻塞队列、优先级队列等。
  • 信号量:用于控制访问资源的数量上限。
  • 发布/订阅:支持消息的发布和订阅机制。
  • 原子操作:提供了类似 AtomicLong 的原子变量,支持跨节点的原子操作。
  • 计数器:支持分布式环境下的计数器,可以用于统计等场景。
  • 监听器:支持监听 Redis 键的变化,方便实现事件驱动的应用程序。

使用场景

  • 分布式缓存:利用 Redisson 的缓存特性加速数据访问。
  • 分布式协调服务:例如使用分布式锁来协调多实例之间的访问顺序。
  • 消息传递:使用 Redisson 的发布/订阅功能来实现消息传递。
  • 限流:使用信号量等功能限制访问频率或并发数量。

开发者友好

Redisson 的设计注重开发者体验,通过 Java 注解等方式简化了开发者的编码工作,同时还提供了详细的文档和示例代码,帮助开发者快速上手。

总结

Redisson 是一个非常强大的工具,可以帮助开发人员更容易地在 Java 应用程序中集成 Redis 的功能,尤其是在构建需要高性能、高可用性的分布式系统时非常有用。通过 Redisson,开发者可以专注于业务逻辑的实现,而不必担心底层的分布式协调和同步问题。

redisson_41">redisson实现分布式

Redisson 是一个基于 Redis 的 Java 客户端库,它提供了一种简便的方式来使用 Redis 的高级功能,包括分布式锁。使用 Redisson 可以简化分布式锁的实现,并且提供了更多的特性和灵活性。

下面是如何使用 Redisson 来实现分布式锁的一个简单示例:

1. 添加依赖

首先,你需要在你的项目中添加 Redisson 的依赖。如果你使用的是 Maven,可以在 pom.xml 文件中添加如下依赖:

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.1</version>
</dependency>

请根据实际版本选择合适的版本号。

2. 配置 RedissonClient

接下来配置一个 RedissonClient 实例,该实例将用于创建锁和其他 Redisson 对象。

java">import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;public class RedissonDistributedLockExample {private static RedissonClient redisson;public static void init() {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");// 根据实际情况配置Redis服务器地址等信息redisson = Redisson.create(config);}
}

3. 获取并使用锁

然后,使用 RLock 接口来获取和释放锁。

java">public class RedissonDistributedLockExample {private static final String LOCK_NAME = "myLock";private static RLock lock = redisson.getLock(LOCK_NAME);public static void main(String[] args) {init();try {// 尝试获取锁,如果锁不可获得,则等待直到获取到锁lock.lock();System.out.println("Lock acquired, performing critical section...");// 执行临界区代码Thread.sleep(5000); // 模拟长时间运行的任务} catch (InterruptedException e) {e.printStackTrace();} finally {// 释放锁if (lock.isHeldByCurrentThread()) {lock.unlock();System.out.println("Lock released.");}}// 关闭 Redisson 客户端redisson.shutdown();}
}

注意事项

  • 线程安全:确保在 finally 块中释放锁,以防锁没有被正确释放导致死锁。
  • 锁超时:虽然上面的例子中没有设置锁的超时时间,但在生产环境中建议为锁设置一个合理的超时时间,以防某个线程无限期持有锁。
  • 异常处理:在实际应用中,应该处理可能出现的各种异常情况,比如网络中断等。

锁超时处理

在使用 Redisson 实现分布式锁时,处理锁的超时是非常重要的,因为它可以防止因持有锁的客户端崩溃而导致的死锁问题。以下是一些处理锁超时的方法:

1. 自动超时设置

Redisson 默认为锁设置了自动过期时间,这个时间可以通过构造函数来指定。例如:

java">RLock lock = redisson.getLock("myLock", new LockOptions(Duration.ofSeconds(30)));

这里设置锁的超时时间为 30 秒。如果在这个时间内锁没有被显式地解锁,那么它会在 30 秒后自动释放。这有助于防止因客户端崩溃而无法释放锁的情况。

2. 动态设置超时时间

也可以在每次获取锁的时候动态设置超时时间:

java">lock.tryLock(10, 30, TimeUnit.SECONDS);

这里第一个参数是等待获取锁的最大时间(10秒),第二个参数是锁的有效时间(30秒)。

3. 监控锁的状态

对于长时间运行的任务,可以周期性地检查锁的状态,并尝试续期锁的有效时间。这可以通过定时任务来实现:

java">ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
scheduledExecutor.scheduleAtFixedRate(() -> {if (lock.isHeldByCurrentThread()) {lock.extend(Duration.ofSeconds(30));}
}, 0, 10, TimeUnit.SECONDS);

这里我们每隔 10 秒检查一次是否还持有锁,如果持有,则将锁的有效时间延长 30 秒。

4. 使用可重入锁

Redisson 支持可重入锁,这意味着同一个线程可以多次获取同一把锁而不会造成死锁。这在某些场景下是有用的,特别是当需要在临界区内再次获取相同的锁时:

java">lock.lock(); // 第一次获取锁
// 执行一些操作
lock.lock(); // 再次获取锁,不会造成死锁
// 执行更多操作
lock.unlock(); // 解锁一次
lock.unlock(); // 再解锁一次,完全释放锁

注意事项

  • 超时时间的选择:选择一个合适的超时时间很重要,太短可能导致正常运行中的任务因超时而被中断,太长则可能在客户端出现问题时无法及时释放锁。
  • 续期策略:如果采用续期策略,需要注意续期逻辑的健壮性,避免续期线程本身出现故障。
  • 资源管理:确保在不再需要锁时正确释放它,并且在程序结束时关闭所有相关资源(如 ScheduledExecutorServiceRedissonClient)。

看门狗机制

Redisson 的分布式锁实现中包含了一个叫做“看门狗”(watchdog)的机制,用来自动延长锁的过期时间。这一机制是为了防止锁的持有者在执行业务逻辑期间意外崩溃,导致锁不能被正常释放,从而引起死锁的问题。

如何工作?

当一个客户端获取了一个锁之后,Redisson 会在 Redis 中为这个锁设置一个过期时间。同时,Redisson 会在本地启动一个定时任务(即看门狗),定期检查这个锁是否仍然由当前客户端持有。如果是的话,看门狗就会自动延长锁在 Redis 中的过期时间。如果锁的持有者在执行过程中崩溃了,那么看门狗也会停止工作,锁会在原有的过期时间到达后自动释放

实现细节

  1. 初始化锁: 当客户端第一次获取锁时,Redisson 会为锁设置一个过期时间(例如 30 秒)。

  2. 启动看门狗: Redisson 同时会在本地启动一个定时任务(例如每 10 秒执行一次),该任务负责检查锁的状态。

  3. 检查锁状态: 如果锁仍然由当前客户端持有,看门狗会将锁的过期时间重置(例如再增加 30 秒)。

  4. 锁的释放: 如果持有锁的客户端正常完成了业务逻辑,它会释放锁;如果客户端崩溃,看门狗也会停止工作,锁将在原始设置的过期时间后自动释放。

示例代码

下面是一个使用 Redisson 实现的带有看门狗机制的分布式锁的简单示例:

java">import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;public class RedissonWatchdogExample {private static final String LOCK_NAME = "myLock";private static RLock lock;private static RedissonClient redisson;public static void init() {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");redisson = Redisson.create(config);lock = redisson.getLock(LOCK_NAME);}public static void main(String[] args) {init();try {// 尝试获取锁,如果锁不可获得,则等待直到获取到锁lock.lock();System.out.println("Lock acquired, performing critical section...");// 执行临界区代码Thread.sleep(5000); // 模拟长时间运行的任务} catch (InterruptedException e) {Thread.currentThread().interrupt();System.err.println("Interrupted while waiting for the lock.");} finally {// 释放锁if (lock.isHeldByCurrentThread()) {lock.unlock();System.out.println("Lock released.");}}// 关闭 Redisson 客户端redisson.shutdown();}
}

注意事项

  • 过期时间设置: 确保设置一个合理的过期时间,这个时间应该比最长时间的业务逻辑执行时间稍长一点,以避免正常执行过程中的误释放。
  • 看门狗间隔: 一般情况下,看门狗的检查间隔应该小于锁的过期时间,以保证锁在长时间运行任务中的安全性。
  • 资源释放: 在使用完毕后,记得释放锁以及关闭 Redisson 客户端,以避免资源泄露。

通过使用 Redisson 的看门狗机制,可以有效地避免因客户端异常退出而导致的死锁问题,从而提高分布式系统的稳定性和可靠性。


http://www.ppmy.cn/devtools/115586.html

相关文章

上海市计算机学会竞赛平台2024年7月月赛丙组子集归零

题目描述 给定 nn 个数字 a1,a2,,…,ana1​,a2​,,…,an​&#xff0c;请统计能从 11 到 nn 中&#xff0c;选出多少种不同的下标子集&#xff0c;使得这些下标对应的数字之和等于 00。 注意空集与全集也是子集中的一种。 输入格式 第一行&#xff0c;单个整数表示 nn第二行…

状态模式:将对象行为与状态解耦

状态模式&#xff08;State Pattern&#xff09;是一种行为设计模式&#xff0c;它允许对象在其内部状态改变时改变其行为&#xff0c;使对象看起来好像修改了其类。 状态模式的核心思想是将对象的行为封装在不同的状态对象中&#xff0c;每个状态对象都代表了对象在某一特定状…

【25.5】C++智能交友系统

实现男生女生自动匹配的功能 void autoPair(const vector <Boy>& boys, const vector <Girl>& girls) {for (int i 0; i < boys.size(); i) {for (int j 0; j < girls.size(); j) {if (boys[i].satisfied(girls[j]) && girls[j].satisfie…

Git常用命令详解

Git 是一个功能强大的版本控制系统&#xff0c;以下是一些常用的 Git 命令及其解释和案例&#xff1a; 1、配置 git config --global user.name "Your Name"&#xff1a;配置全局用户名。 git config --global user.email "emailexample.com&#xff1a;配置全…

spring boot 定时器配置

1、首先在主类上加EnableScheduling注解 2、在应用类上加Scheduled注解&#xff0c;同时记得添加spring的组件注解Component&#xff0c;不然无法成功

Qt:静态局部变量实现单例(附带单例使用和内存管理)

前言 本文主要写静态局部变量实现的单例以及单例的释放&#xff0c;网上很多教程只有单例的创建&#xff0c;但是并没有告诉我们单例的内存管理&#xff0c;这就很头疼。静态局部变量实现的单例应该是最简单的单例&#xff0c;而且不需要内存管理。 正文 静态局部变量单例&a…

python --PyAibote自动化

官文: https://www.pyaibote.com/ 下载安卓集成环境: 可以看到开发的一些信息

【Python报错已解决】 Requests.exceptions.ProxyError: HTTPSConnectionPool

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…