一、Redisson
- 一个用来进行分布式锁的工具类
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.8</version>
</dependency>
1. 基本Demo
package com.erick.redis;
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 Test03 {
public static void main(String[] args) {
new Thread(() -> lockWithBusiness()).start();
new Thread(() -> lockWithBusiness()).start();
}
private static void lockWithBusiness() {
RedissonClient redissonClient = redissonClient();
/*获取对应的key的锁*/
String lockKey = "COMMERCE-BUSINESS";
RLock lock = redissonClient.getLock(lockKey);
try {
// 内部包含重试时间
/*参数一: 最长等待时间
* 参数二:锁超时释放时间
* 参数三:时间单位*/
boolean hasLok = lock.tryLock();
if (hasLok) {
business();
} else {
System.out.println("暂时没有获取到锁");
}
} finally {
/*第二个锁释放的时候,会报 删除异常
* IllegalMonitorStateException*/
lock.unlock();
}
}
/*等待超时的锁*/
private static void lockWithBusinessWithTime() {
RedissonClient redissonClient = redissonClient();
/*获取对应的key的锁*/
String lockKey = "COMMERCE-BUSINESS";
RLock lock = redissonClient.getLock(lockKey);
try {
// 内部包含重试时间
/*参数一: 最长等待时间
* 参数二:锁超时释放时间
* 参数三:时间单位*/
boolean hasLok = lock.tryLock(6, 20, TimeUnit.SECONDS);
if (hasLok) {
business();
} else {
System.out.println("暂时没有获取到锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 最长等待时间获取不到,删除的时候依然会报错
lock.unlock();
}
}
private static void business() {
System.out.println("执行业务");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*Redis的配置类*/
private static RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress("redis://60.205.229.31:6380");
return Redisson.create(config);
}
}
2. 可重入性
2.1 不可重入锁
2.2 可重入锁
- 存储的键值对用Hash结构来保存
- 为了保证多条命令的原子性,必须采取lua脚本来做
2.3 lua脚本
3. 重试机制
- 通过等待时间结合,发布以及订阅模式来实现
4. 主从一致性
4.1 问题
4.2 联锁
- 解决方案:设立多个redis作为主节点
- 只有每个都获取成功的时候,才会去执行
package com.erick.redis;
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 Test04 {
public static void main(String[] args) {
businessWithLock();
}
private static void businessWithLock() {
String lockKey = "BUSINESS";
RedissonClient firstClient = redissonClient01();
RedissonClient secondClient = redissonClient02();
RedissonClient thirdClient = redissonClient03();
RLock firstLock = firstClient.getLock(lockKey);
RLock secondLock = secondClient.getLock(lockKey);
RLock thirdLock = thirdClient.getLock(lockKey);
/*获取到多把锁*/
RLock multiLock = firstClient.getMultiLock(firstLock, secondLock, thirdLock);
boolean hasLock = multiLock.tryLock();
try{
if (hasLock) {
business();
} else {
System.out.println("未获取到锁,业务没有执行");
}
}finally {
multiLock.unlock();
}
}
private static void business() {
System.out.println("执行业务");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*Redis的配置类*/
private static RedissonClient redissonClient01() {
Config config = new Config();
config.useSingleServer().setAddress("redis://60.205.229.31:6379");
return Redisson.create(config);
}
private static RedissonClient redissonClient02() {
Config config = new Config();
config.useSingleServer().setAddress("redis://60.205.229.31:6380");
return Redisson.create(config);
}
private static RedissonClient redissonClient03() {
Config config = new Config();
config.useSingleServer().setAddress("redis://60.205.229.31:6381");
return Redisson.create(config);
}
}