https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.14.1</version> </dependency>
以配置类的形式设置
@Configuration public class MyRedisConfig { @Bean public RedissonClient redissonClient(){ Config config = new Config(); //配置链接的信息 config.useSingleServer().setAddress("redis://192.168.1.137:6379"); RedissonClient redissonClient = Redisson.create(); return redissonClient; } }
ls -l /proc/7579/cwd
接下来我们看 分布式锁 的可重入锁(Reentrant Lock) 同一个对象的同一把锁 是可以进入
@ResponseBody @GetMapping("/hello") public String hello(){ RLock myLock = redissonClient.getLock("myLock"); // 加锁 // myLock.lock(); //通过效果演示我们可以发现 指定了过期时间后 自动续期就不会生效了 这时我们就需要注意设置过期时间一定要满足我们得业务场景 默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过yml修改Config.lockWatchdogTimeout来另行指定
另外Redisson还通过加锁的方法提供了leaseTime
的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
// 加锁以后10秒钟自动解锁 // 无需调用unlock方法手动解锁 lock.lock(10, TimeUnit.SECONDS); // 尝试加锁,最多等待100秒,上锁以后10秒自动解锁 boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS); if (res) { try { ... } finally { lock.unlock(); } }
//如果我们指定了锁的过期时间 那么在源码中会直接帮我们创建一个过期时间是指定的锁 时间到期后就会把该锁删除 //如果我们没有指定过期时间 那么在执行的时候 首先会创建一把锁且过期时间是30秒 然后会创建异步任务 每隔10秒 去执行任务来续期 //实际开发中 我们最好指定过期时间---》性能考虑--》计算代码的执行时间 myLock.lock(10, TimeUnit.SECONDS);//过期时间是10s 业务时间超过10s 会不会自动续期 try { System.out.println("加锁成功...业务处理....." + Thread.currentThread().getName()); Thread.sleep(30000); }catch (Exception e){ }finally { System.out.println("释放锁成功..." + Thread.currentThread().getName()); // 释放锁 myLock.unlock(); } return "hello"; }
公平锁(Fair Lock)保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,
Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。
RLock fairLock = redisson.getFairLock("anyLock");
// 最常见的使用方法
fairLock.lock();
大家都知道,如果负责储存这个分布式锁的Redis节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了leaseTime
的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
fairLock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
...
fairLock.unlock();
读写锁(ReadWriteLock)分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常见的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();
大家都知道,如果负责储存这个分布式锁的Redis节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了leaseTime
的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// 或
rwlock.writeLock().lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// 或
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();
-------------------------------------------------------------
根据业务操作我们可以分为读写操作,读操作其实不会影响数据,那么如果还对读操作做串行处理,效率会很低,这时我们可以通过读写锁来解决这个问题
在读写锁中,只有读读的行为是共享锁,相互之间不影响,只要有写的行为存在,那么就是一个互斥锁(排他锁)
---------------------------------------------------------------------------------------------
@GetMapping("/write") @ResponseBody public String writeValue(){ RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock"); //加写锁 RLock rLock = readWriteLock.writeLock(); String s=null; rLock.lock(); try { System.out.println("写锁成功"); s = UUID.randomUUID().toString(); stringRedisTemplate.opsForValue().set("msg", s); Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); }finally { rLock.unlock(); } return s; } /** * 读读操作 相当于没有加锁 * 写 读操作 需要等待写锁释放 读锁才能读取 阻塞 * 写 写 阻塞方式 * 读写 读数据的时候也会添加锁 那么写的行为也会阻塞 * @return */ @GetMapping("/read") @ResponseBody public String readValue(){ RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock"); //加读锁 RLock rLock = readWriteLock.readLock(); rLock.lock(); String s = null; try { System.out.println("读锁成功"); s = stringRedisTemplate.opsForValue().get("msg"); Thread.sleep(30000); } catch (Exception e) { e.printStackTrace(); } finally { // rLock.unlock(); } return s; }
闭锁 基于Redisson的Redisson分布式闭锁 @ResponseBody @GetMapping("/lockDoor") public String lockDoor() { RCountDownLatch door = redissonClient.getCountDownLatch("door");//阻塞 等待count 等于0 时才能继续执行 door.trySetCount(5); try { door.await();//阻塞等待5个执行完 } catch (InterruptedException e) { e.printStackTrace(); } return "关门熄灯"; } @GetMapping("/goHome/{id}") @ResponseBody public String goHome(@PathVariable Long id){ RCountDownLatch door = redissonClient.getCountDownLatch("door"); door.countDown(); return id+"下班走人"; }
信号量(Semaphore) 基于Redis的Redisson的分布式信号量 限流 @GetMapping("/park") @ResponseBody public String park(){ RSemaphore park = redissonClient.getSemaphore("park"); boolean b = true; try { // park.acquire(); // 获取信号 阻塞到获取成功 b = park.tryAcquire();// 返回获取成功还是失败 } catch (Exception e) { e.printStackTrace(); } return "停车是否成功:" + b; } @GetMapping("/release") @ResponseBody public String release(){ RSemaphore park = redissonClient.getSemaphore("park"); park.release(); return "释放了一个车位"; }
本文摘自 :https://www.cnblogs.com/