springboot实现分布式锁,java实现分布式锁,redisson实现分布式锁


一、Redisson

Redisson是Redis官方推荐的Java版的Redis客户端。它提供的功能非常多,也非常强大,这里我们学习使用它的分布式锁功能。

二、java实现Redisson,实现锁需求

pom添加

<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.15.0</version>
</dependency>
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import java.util.concurrent.TimeUnit;

public class Test {
public static void main(String args[]) {
// 创建redisson配置
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("password");
// 2. 创建redisson实例
RedissonClient client = Redisson.create(config);
String lockStr = "LOCK_STR";
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("第1个线程已启动");
RLock lock = client.getFairLock(lockStr);
try {
//五秒内不停尝试去获得锁,如果获得成功,则返回true,获得失败返回false
boolean b = lock.tryLock(5, TimeUnit.SECONDS);
if(b) {
System.out.println("第1个线程已获得锁");
//执行代码业务逻辑
// .......
//一定要记得unlock,其他线程才能得到锁。不然线程不停,线程越积越多,可能会内存溢出或者其他错误
lock.unlock();
System.out.println("第1个线程已释放锁");
}else{
//代表五秒后,依然未得到锁就会进入当前代码
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();

new Thread(new Runnable() {
@Override
public void run() {
System.out.println("第2个线程已启动");
RLock lock = client.getFairLock(lockStr); //获得公平锁,公平锁和非公平锁都能实现 分布式锁需求。区别是公平锁讲究先来后到,先来的先得到锁
//client.getLock(lockStr); //获得锁
try {
//五秒内不停尝试去获得锁,如果获得成功,则返回true,获得失败返回false
boolean b = lock.tryLock(5, TimeUnit.SECONDS);
if(b) {
System.out.println("第2个线程已获得锁");
//执行代码业务逻辑
// .......
//一定要记得unlock,其他线程才能得到锁。不然线程不停,线程越积越多,可能会内存溢出或者其他错误
lock.unlock();
System.out.println("第2个线程已释放锁");
}else{
//代表五秒后,依然未得到锁就会进入当前代码
return;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}

执行效果:

第1个线程已启动
第2个线程已启动
第2个线程已获得锁
第2个线程已释放锁
第1个线程已获得锁
第1个线程已释放锁

三、SpringBoot实现Redisson,实现分布式锁需求

pom添加

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

增加配置类:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {

@Value("${spring.redis.host}")
private String host;

@Value("${spring.redis.port}")
private String port;

@Value("${spring.redis.password}")
private String password;

@Bean
public RedissonClient getRedisson(){
Config config = new Config();
config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
RedissonClient client = Redisson.create(config);
return client;
}
}

业务逻辑代码:

@Service
public class TheaterOrderJob {

@Resource
private RedissonClient redissonClient;

public void lockTicket() { //例如 影院订票锁座功能 集群环境需要实现分布式锁
try {
//采用集群共享锁机制,来解决多应该同时执行定时任务问题
RLock lock = redissonClient.getLock("redisson_cancel_order");
boolean b = lock.tryLock(10, TimeUnit.SECONDS);
//b为 true则代表已获得锁
if(b) {
//执行业务逻辑,例如锁座,集群环境下,多个实例 只有得到锁后才能 锁座,同一时间只有一个实例在执行
//.....
lock.unlock();//解锁
}else{
//未获得锁执行代码
//....
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

加上redisson锁在集群环境下,只有一个实例在执行锁内的代码中,不会出现多个实例执行导致数据不一致情况。