Redisson的基本使用
一、概述
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
Redisson和jedis以及lettuce一样都是redis客户端,只不过Redisson功能更强大。
官方文档:https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95
二、Redisson的使用
2.1 搭建环境
① 引入redssion坐标依赖:
<!-- 以后使用redisson作为所有分布式锁,分布式对象等功能框架--> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.0</version> </dependency>
② 配置redisson,程序化的配置方法是通过构建Config对象实例来实现的:
@Configuration public class MyRedissonConfig { //注册RedissonClient对象 @Bean(destroyMethod="shutdown") RedissonClient redisson() throws IOException { Config config = new Config(); config.useSingleServer().setAddress("redis://192.168.182.150:6379"); RedissonClient redissonClient = Redisson.create(config); return redissonClient; } }
2.2 可重入锁(Reentrant Lock)
@ResponseBody @GetMapping("/hello") public String hello(){ //获取一把锁 RLock lock = redissonClient.getLock("my-lock"); //加锁 lock.lock(); //锁的自动续期,如果业务执行时间超长,运行期间会自动给锁续期30秒时间,不用担心业务时间长,锁自动过期 //加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30秒后也会自动删除 try { System.out.println("加锁成功,执行业务.... "+Thread.currentThread().getId()); Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } finally { //手动解锁 System.out.println("解锁..."+Thread.currentThread().getId()); lock.unlock(); } return "hello"; }
如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
@ResponseBody @GetMapping("/hello") public String hello(){ //获取一把锁 RLock lock = redissonClient.getLock("my-lock"); // 加锁 // 设置的自动解锁时间一定要大于业务执行时间,因为在锁时间到了以后,不会自动续期 lock.lock(10, TimeUnit.SECONDS); try { System.out.println("加锁成功,执行业务.... "+Thread.currentThread().getId()); Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } finally { //解锁 System.out.println("解锁..."+Thread.currentThread().getId()); lock.unlock(); } return "hello"; }
结论:
- lock.lock()即没有指定锁的过期时间,就是用30s,即看门狗的默认时间,只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10秒就会自动续期到30秒。
- lock.lock(10, TimeUnit.SECONDS),默认锁的过期时间就是我们指定的时间。
2.3 读写锁
基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。其中读锁和写锁都继承了RLock接口。
分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
① 读锁
@GetMapping("/read")
public String readValue(){
RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
String s = "";
//加读锁
RLock rLock = lock.readLock();
rLock.lock();
try {
System.out.println("读锁加锁成功"+Thread.currentThread().getId());
s = redisTemplate.opsForValue().get("writeValue");
Thread.sleep(30000);
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
System.out.println("读锁释放"+Thread.currentThread().getId());
}
return s;
}
② 写锁
@GetMapping("/write")
public String writeValue(){
// 获取一把锁
RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
String s = "";
// 加写锁
RLock rLock = lock.writeLock();
try {
//1、改数据加写锁,读数据加读锁
rLock.lock();
System.out.println("写锁加锁成功..."+Thread.currentThread().getId());
s = UUID.randomUUID().toString();
Thread.sleep(30000);
redisTemplate.opsForValue().set("writeValue",s);
} catch (Exception e) {
e.printStackTrace();
} finally {
rLock.unlock();
System.out.println("写锁释放"+Thread.currentThread().getId());
}
return s;
}
测试:
先加写锁,后加读锁,此时并不会立刻给数据加读锁,而是需要等待写锁释放后,才能加读锁
先加读锁,再加写锁:有读锁,写锁需要等待
先加读锁,再加读锁:并发读锁相当于无锁模式,会同时加锁成功
总结:只要有写锁的存在,都必须等待,写锁是一个排他锁,只能有一个写锁存在,读锁是一个共享锁,可以有多个读锁同时存在。
2.4 信号量(Semaphore)
基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法
RSemaphore semaphore = redisson.getSemaphore("semaphore");
semaphore.acquire();
//或
semaphore.acquireAsync();
semaphore.acquire(23);
semaphore.tryAcquire();
//或
semaphore.tryAcquireAsync();
semaphore.tryAcquire(23, TimeUnit.SECONDS);
//或
semaphore.tryAcquireAsync(23, TimeUnit.SECONDS);
semaphore.release(10);
semaphore.release();
//或
semaphore.releaseAsync();
2.5 闭锁(CountDownLatch)
基于Redisson的Redisson分布式闭锁(CountDownLatch)Java对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.trySetCount(1);
latch.await();
// 在其他线程或其他JVM里
RCountDownLatch latch = redisson.getCountDownLatch("anyCountDownLatch");
latch.countDown();

浙公网安备 33010602011771号