1、首先,我们需要引入相关依赖(请根据你的spring boot版本)
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.1</version>
</dependency>
2、使用配置文件的方式进行配置:
package com.example.rabbitmq.mqConfig;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
@Configuration
public class MyredissonConfig{
@Bean
public RedissonClient redissonClient() throws IOException{
Config config = new Config();
// 这里要注意一下要写:redis://
config.useSingleServer().setAddress("redis://192.168.56.10:6379");
config.setLockWatchdogTimeout(30000);//设置看门狗的默认时间
RedissonClient redissonClient = Redisson.create(config);
return redissonClient;
}
}
3、下面我们用几个案例来看一下rediss 里面的各种分布式锁:
package com.example.rabbitmq.app;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/redis")
public class RedissonTest {
@Autowired
private RedissonClient redissonClient;
/**
* 1、普通锁,自带安全狗机制
*/
@GetMapping("/lock")
public void getlock(){
RLock lock = redissonClient.getLock("lock");
if(lock!=null){
try {
lock.lock();
System.out.println("无过期时间锁,安全狗自动设置30S ,且自动续锁");
Thread.sleep(50000);
}catch (Exception e){
}finally {
System.out.println("业务执行完毕,开始释放锁...");
lock.unlock();
}
}
}
/**
* 带过期时间的锁(如果我们设置了过期时间,则不会启动看门狗)
* 这里要说明一下,我们尽量让锁的过期时间长于业务时间
*/
@GetMapping("/lockTime")
public void getlockTime(){
RLock lock = redissonClient.getLock("lockTime");
if(lock!=null){
try {
lock.lock(30, TimeUnit.SECONDS);
System.out.println("无过期时间锁,安全狗自动设置30S ,且自动续锁");
Thread.sleep(50000);
}catch (Exception e){
}finally {
System.out.println("业务执行完毕,开始释放锁...");
lock.unlock();
}
}
}
/**
* trylock 用于尝试获取锁,如果不能获取则等待
*
* tryLock里面有三个参数:
* watiTime: 等待锁的最大时间,超过时间不再尝试获取所。
* leaseTime:如果没有手动调用unlock,超过时间自动释放
* TimeUnit :释放时间单位。
*/
@GetMapping("/tryLockTime")
public void getTrylockTime() throws InterruptedException {
RLock lock = redissonClient.getLock("lockTime");
if(lock.tryLock(45,30,TimeUnit.SECONDS)){
System.out.println("获取锁成功");
}
Thread.sleep(50000);
lock.unlock();
}
/**
* 公平锁 getFairLock
* Redisson公平锁原理
* JDK中也有公平锁和非公平锁,所谓公平锁,
* 就是保证客户端获取锁的顺序,跟他们请求获取锁的顺序,是一样的。
* 公平锁需要排队,谁先申请获取这把锁,谁就可以先获取到这把锁,
* 是按照请求的先后顺序来的。
*/
@GetMapping("/fairLock")
public void testFairLock(){
RLock fairLock = redissonClient.getFairLock("anyLock");
try{
// 最常见的使用方法
fairLock.lock();
// 支持过期解锁功能, 10秒钟以后自动解锁,无需调用unlock方法手动解锁
fairLock.lock(10, TimeUnit.SECONDS);
// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = fairLock.tryLock(100, 10, TimeUnit.SECONDS);
// Redisson同时还为分布式可重入公平锁提供了异步执行的相关方法:
// RLock fairLock = redisson.getFairLock("anyLock");
// fairLock.lockAsync();
// fairLock.lockAsync(10, TimeUnit.SECONDS);
// Future<Boolean> res = fairLock.tryLockAsync(100, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
fairLock.unlock();
}
}
/**
* 读写锁
* Redisson的分布式可重入读写锁RReadWriteLock,Java对象实现了
* java.util.concurrent.locks.ReadWriteLock接口。同时还支持自动过期解锁。
* 该对象允许同时有多个读取锁,但是最多只能有一个写入锁。
*/
@GetMapping("readWriteLock")
public void getReadWriteLock(){
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("readWriteLock");
if(readWriteLock!=null){
try {
readWriteLock.readLock().lock();// 读锁
readWriteLock.writeLock().lock();//写锁,排他锁
}catch (Exception E){
}finally {
readWriteLock.readLock().unlock();
readWriteLock.writeLock().unlock();
}
}
}
/**
* 信号量(Semaphore)
* Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了
* 与java.util.concurrent.Semaphore相似的接口和用法。
*/
/// Redisson 信号量 可以用来做限流处理
@GetMapping("/park")
public String park() throws InterruptedException {
//和锁一样 随便指定一个名字 只要名字相同获取的就是同一个信号量
RSemaphore park = redissonClient.getSemaphore("park");
// park.acquire();//阻塞式方法 获取成功执行下面 获取不成功就一直在这一句卡住
//占成功了 redis里这个信号量的值就会 减一
park.trySetPermits(5);// 设置信号量总量
boolean b = park.tryAcquire();//消耗一个信号量 类似于 --
if(b){
//执行业务
return "park =>信号量有值 获取成功 可以执行业务";
}else{
return "park => 没有获取到信号量";
}
}
@GetMapping("/go")
public String go(){
RSemaphore park = redissonClient.getSemaphore("park");
park.release();//执行这一句 信号量的值加一。类似于 ++
return "go";
}
}