这里写自定义目录标题
同一个JVM进程内中执行任务通常我们synchronized 、Lock锁,但是在集群作业时就要使用分布式锁了,常见的分布式锁有zookeeper、redis以及数据库锁等
这里使用Reids分布式锁,废话不多说上代码
一:引入redis的包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.0.1</version>
</dependency>
二:redis链接池
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* redis数据库连接池
*/
public class RedisDB {
private static JedisPoolConfig config=null;
private static JedisPool jedisPool;
/**
* 初始化数据量连接池
* @param host redis地址
* @param port redis端口
* @param maxTotal 最大活动对象数
* @param maxIdle 最大能够保持idel状态的对象数
*/
public static void init(String host,int port,int maxTotal,int maxIdle){
config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
jedisPool = new JedisPool(config,host,port);
}
/**
* 获取Jedis
* @return
*/
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
三:redis锁
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
import java.util.Collections;
public class RedisLockUtil {
private static final String LOCK_SUCCESS = "OK";
private static final Long RELEASE_SUCCESS = 1L;
private static long timeout = 999999; //获取锁的超时时间
/**
* 获取锁
* @param lockName 锁的名称
* @param requestId 请求ID,一般用UUID(用于记录谁申请的锁)
* @param expireTime 过期时间
* @return 是否成功
*/
public static boolean getLock(Jedis jedis, String lockName,String requestId, int expireTime){
Long start = System.currentTimeMillis();
SetParams params = new SetParams();
params.ex(expireTime); // 设置超时时间
params.nx(); // 若锁不存在才进行写操作
try {
for(;;) {
//SET命令返回OK ,则证明获取锁成功
String result = jedis.set(lockName, requestId, params);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
//否则循环等待,在timeout时间内仍未获取到锁,则获取失败
long l = System.currentTimeMillis() - start;
if (l>=timeout) {
return false;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
jedis.close();
}
return false;
}
/**
* 删除锁
* @param lockName 锁的名称
* @param requestId 请求ID,一般用UUID(用于记录谁申请的锁)
* @return 是否成功
*/
public static boolean deleteLock(Jedis jedis,String lockName,String requestId){
try {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockName), Collections.singletonList(requestId));
return RELEASE_SUCCESS.equals(result);
}catch (Exception e){
e.printStackTrace();
}finally {
jedis.close();
}
return false;
}
}
四:使用方法
import com.suishouji.redis.db.RedisDB;
import com.suishouji.redis.lock.RedisLockUtil;
import redis.clients.jedis.Jedis;
import java.util.UUID;
public class RedisLockTest {
public static void main(String[] args) {
//链接redis
RedisDB.init("127.0.0.1",6379,50,10);
String lockName="testLock";
//获取锁
Jedis jedis = RedisDB.getJedis();
String requestId=UUID.randomUUID().toString();
boolean lock = RedisLockUtil.getLock(jedis, lockName, requestId, 7200);
if(lock) {
System.out.println("被锁的区域");
jedis = RedisDB.getJedis();
//解锁
RedisLockUtil.deleteLock(jedis,lockName,requestId);
}else{
System.out.println("锁获取失败");
}
}
}