经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Redis » 查看文章
Redisson分布式锁
来源:cnblogs  作者:coffee_baby  时间:2024/3/1 8:43:09  对本文有异议

Redisson分布式锁

来自Githup官方文档的介绍:

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

官方文档地址:https://github.com/redisson/redisson/wiki

中文文档地址:https://github.com/redisson/redisson/wiki/目录

先讲一下为什么使用分布式锁:

在传统的单体应用中,我们可以使用Java并发处理相关的API(如ReentrantLock或synchronized)来实现对共享资源的互斥控制,确保在高并发情况下同一时间只有一个线程能够执行特定方法。然而,随着业务的发展,单体应用逐渐演化为分布式系统,多线程、多进程分布在不同机器上,这导致了原有的单机部署下的并发控制策略失效。为了解决这一问题,我们需要引入一种跨JVM的互斥机制来管理共享资源的访问,这就是分布式锁所要解决的核心问题。

SpringBoot框架整合

1.引入依赖

  1. <dependency>
  2. <groupId>org.redisson</groupId>
  3. <artifactId>redisson-spring-boot-starter</artifactId>
  4. <version>3.15.5</version>
  5. </dependency>

2.创建配置类

  1. @Configuration
  2. public class RedissonConfig {
  3. @Value("${spring.redis.host}")
  4. private String redisHost;
  5. @Value("${spring.redis.port}")
  6. private int redisPort;
  7. @Value("${spring.redis.password}")
  8. private String password;
  9. @Value("${spring.redis.database}")
  10. private int database;
  11. @Bean
  12. public RedissonClient redissonClient() {
  13. Config config = new Config();
  14. config.useSingleServer()
  15. .setAddress("redis://" + redisHost + ":" + redisPort)
  16. .setPassword(password)
  17. .setDatabase(database)
  18. .setConnectionMinimumIdleSize(10) // 连接池最小空闲连接数
  19. .setConnectionPoolSize(50) // 连接池最大连接数
  20. .setIdleConnectionTimeout(60000) // 线程超时时间
  21. .setConnectTimeout(60000) // 客户端程序获取redis连接超时时间
  22. .setTimeout(60000); // 响应超时时间
  23. return Redisson.create(config);
  24. }
  25. }

集群的配置参考:https://github.com/redisson/redisson/wiki/2.-配置方法#24-集群模式

3.实际使用

  1. public void checkAndLock5() {
  2. RLock redisson_lock = redissonClient.getLock("redisson_lock");
  3. try{
  4. redisson_lock.lock();
  5. // 1. 业务代码
  6. }finally {
  7. redisson_lock.unlock();
  8. }
  9. }

可重入锁(Reentrant Lock)

基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。同时还提供了异步(Async)反射式(Reactive)RxJava2标准的接口

  1. RLock lock = redisson.getLock("anyLock");
  2. // 最常见的使用方法
  3. lock.lock();

大家都知道,如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

  1. // 加锁以后10秒钟自动解锁
  2. // 无需调用unlock方法手动解锁
  3. lock.lock(10, TimeUnit.SECONDS);
  4. // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
  5. boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
  6. if (res) {
  7. try {
  8. ...
  9. } finally {
  10. lock.unlock();
  11. }
  12. }

公平锁(Fair Lock)

基于Redis的Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。同时还提供了异步(Async)反射式(Reactive)RxJava2标准的接口。它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。

  1. RLock fairLock = redisson.getFairLock("anyLock");
  2. // 最常见的使用方法
  3. fairLock.lock();

大家都知道,如果负责储存这个分布式锁的Redis节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

  1. // 10秒钟以后自动解锁
  2. // 无需调用unlock方法手动解锁
  3. fairLock.lock(10, TimeUnit.SECONDS);
  4. // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
  5. boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
  6. ...
  7. fairLock.unlock();

联锁(MultiLock)

基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。

  1. RLock lock1 = redissonInstance1.getLock("lock1");
  2. RLock lock2 = redissonInstance2.getLock("lock2");
  3. RLock lock3 = redissonInstance3.getLock("lock3");
  4. RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
  5. // 同时加锁:lock1 lock2 lock3
  6. // 所有的锁都上锁成功才算成功。
  7. lock.lock();
  8. ...
  9. lock.unlock();

大家都知道,如果负责储存某些分布式锁的某些Redis节点宕机以后,而且这些锁正好处于锁住的状态时,这些锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

  1. RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
  2. // 给lock1,lock2,lock3加锁,如果没有手动解开的话,10秒钟后将会自动解开
  3. lock.lock(10, TimeUnit.SECONDS);
  4. // 为加锁等待100秒时间,并在加锁成功10秒钟后自动解开
  5. boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
  6. ...
  7. lock.unlock();

红锁(RedLock)

基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。

  1. RLock lock1 = redissonInstance1.getLock("lock1");
  2. RLock lock2 = redissonInstance2.getLock("lock2");
  3. RLock lock3 = redissonInstance3.getLock("lock3");
  4. RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
  5. // 同时加锁:lock1 lock2 lock3
  6. // 红锁在大部分节点上加锁成功就算成功。
  7. lock.lock();
  8. ...
  9. lock.unlock();

大家都知道,如果负责储存某些分布式锁的某些Redis节点宕机以后,而且这些锁正好处于锁住的状态时,这些锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

  1. RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
  2. // 给lock1,lock2,lock3加锁,如果没有手动解开的话,10秒钟后将会自动解开
  3. lock.lock(10, TimeUnit.SECONDS);
  4. // 为加锁等待100秒时间,并在加锁成功10秒钟后自动解开
  5. boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
  6. ...
  7. lock.unlock();

读写锁(ReadWriteLock)

基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。其中读锁和写锁都继承了RLock接口。

分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。

  1. RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
  2. // 最常见的使用方法
  3. rwlock.readLock().lock();
  4. // 或
  5. rwlock.writeLock().lock();

大家都知道,如果负责储存这个分布式锁的Redis节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

  1. // 10秒钟以后自动解锁
  2. // 无需调用unlock方法手动解锁
  3. rwlock.readLock().lock(10, TimeUnit.SECONDS);
  4. // 或
  5. rwlock.writeLock().lock(10, TimeUnit.SECONDS);
  6. // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
  7. boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
  8. // 或
  9. boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
  10. ...
  11. lock.unlock();

信号量(Semaphore)

基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。同时还提供了异步(Async)反射式(Reactive)RxJava2标准的接口。

  1. RSemaphore semaphore = redisson.getSemaphore("semaphore");
  2. semaphore.acquire();
  3. //或
  4. semaphore.acquireAsync();
  5. semaphore.acquire(23);
  6. semaphore.tryAcquire();
  7. //或
  8. semaphore.tryAcquireAsync();
  9. semaphore.tryAcquire(23, TimeUnit.SECONDS);
  10. //或
  11. semaphore.tryAcquireAsync(23, TimeUnit.SECONDS);
  12. semaphore.release(10);
  13. semaphore.release();
  14. //或
  15. semaphore.releaseAsync();

闭锁(CountDownLatch)

基于Redisson的Redisson分布式闭锁(CountDownLatch)Java对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。

  1. RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
  2. latch.trySetCount(1);
  3. latch.await();
  4. // 在其他线程或其他JVM里
  5. RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
  6. latch.countDown();

原文链接:https://www.cnblogs.com/dupengpeng/p/18044474

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号