?xml version="1.0" encoding="UTF-8"?
### 背景:为什么要写这篇文章呢
最近做的项目遇到了一个问题,就是分布式xxl_job任务框架的分布式部署后,任务采用轮训方式在多台服务器执行,某个和数据库有交互的任务每隔5分钟定时执行一次。比如第一次9:00在服务器A上执行,第二次9:05则到了服务器B上执行,这时候同样的代码执行了2次,造成数据交互错乱。
### 调研如何解决这个问题
刚开始想到使用项目中已经在使用的redis来解决这个问题,因为redis在我们项目中已经使用的比较成熟,比如用户登录认证的token,过期刷新用的 refresh_token、以及gateway网关的服务路由等都是存储在redis里面的。
### 实现方式一(有不足点)
刚开始同事想到的实现方式就是job在服务器A执行的时候,直接put 一个key到redis的库中,等执行结束的时候,在清除掉。这样,当job在服务器执行的时候,会先检查这个key是否在存在库中,如果存在,就退出执行,不存在的话,加锁,继续执行,执行完成,释放锁。
但是上面的方式经我提醒后,存在不足点。最大的不足,在于redis的锁(key)需要设置过期时间,如果job在服务器A上执行到一半代码的时候,所突然过期了,这时候服务器B上的job执行,就会重入这块代码,依然造成数据冲突,解决不了最新提出的问题。
### 改进后的执行方式
后面我调研了一下开源的Redisson框架,发现Redisson刚好能解决这个问题,并且使用方式简单。
### 具体使用方式
1. maven依赖
-
2. 配置类代码实现
```
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("${redis.host}")
private String host;
@Value("${redis.database}")
private Integer database;
@Value("${redis.port}")
private Integer port;
@Bean
public RedissonClient redisson(){
Config config = new Config();
config.useSingleServer().setAddress("redis://"+host+":"+port).setPassword("asasa").setDatabase(database);
return Redisson.create(config);
}
}
function fun(){
echo "这是一句非常牛逼的代码";
}
fun();
```
3. 使用类代码举例
```
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.*;
public class DbCreateHandler extends IJobHandler {
@Autowired
RedissonClient redissonClient;
@Value("${spring.application.name}")
private String applicationName;
@Override
public JobWrapper
int code = -1;
String message = "";
String lockKey = applicationName+"_dbCreateHandler";
RLock redissonLock = redissonClient.getLock(lockKey);
try {
//默认超时时间30S
redissonLock.lock();
}catch(Exception e){
e.printStackTrace();
}finally{
redissonLock.unlock();
}
return jobWrapper;
}
}
```
### 原理说明
1. Redisson分布式锁实现原理图
![4010b729a16a32e1d8853317bc6f34f5.png](evernotecid://CCCDFA6D-243E-4347-BAC7-B1F0633DCBB2/appyinxiangcom/32899750/ENResource/p842)
2. 源码说明