com.crossoverjie.distributed.lock.RedisLock Maven / Gradle / Ivy
package com.crossoverjie.distributed.lock;
import com.crossoverjie.distributed.util.ScriptUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisCommands;
import java.util.Collections;
/**
* Function: distributed lock
*
* @author crossoverJie
* Date: 26/03/2018 11:09
* @since JDK 1.8
*/
public class RedisLock {
private static final String LOCK_MSG = "OK";
private static final Long UNLOCK_MSG = 1L;
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
private String lockPrefix;
private int sleepTime;
private JedisCommands jedis;
/**
* time millisecond
*/
private static final int TIME = 1000;
/**
* lua script
*/
private String script;
private RedisLock(Builder builder) {
this.jedis = builder.jedis;
this.lockPrefix = builder.lockPrefix;
this.sleepTime = builder.sleepTime;
buildScript();
}
/**
* Non-blocking lock
*
* @param key lock business type
* @param request value
* @return true lock success
* false lock fail
*/
public boolean tryLock(String key, String request) {
String result = this.jedis.set(lockPrefix + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
if (LOCK_MSG.equals(result)) {
return true;
} else {
return false;
}
}
/**
* blocking lock
*
* @param key
* @param request
*/
public void lock(String key, String request) throws InterruptedException {
for (; ; ) {
String result = this.jedis.set(lockPrefix + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
if (LOCK_MSG.equals(result)) {
break;
}
Thread.sleep(sleepTime);
}
}
/**
* blocking lock,custom time
*
* @param key
* @param request
* @param blockTime custom time
* @return
* @throws InterruptedException
*/
public boolean lock(String key, String request, int blockTime) throws InterruptedException {
while (blockTime >= 0) {
String result = this.jedis.set(lockPrefix + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
if (LOCK_MSG.equals(result)) {
return true;
}
blockTime -= sleepTime;
Thread.sleep(sleepTime);
}
return false;
}
/**
* Non-blocking lock
*
* @param key lock business type
* @param request value
* @param expireTime custom expireTime
* @return true lock success
* false lock fail
*/
public boolean tryLock(String key, String request, int expireTime) {
String result = this.jedis.set(lockPrefix + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_MSG.equals(result)) {
return true;
} else {
return false;
}
}
/**
* unlock
*
* @param key
* @param request request must be the same as lock request
* @return
*/
public boolean unlock(String key, String request) {
//lua script
Object result = null;
if (jedis instanceof Jedis) {
result = ((Jedis) this.jedis).eval(script, Collections.singletonList(lockPrefix + key), Collections.singletonList(request));
} else if (jedis instanceof JedisCluster) {
result = ((JedisCluster) this.jedis).eval(script, Collections.singletonList(lockPrefix + key), Collections.singletonList(request));
} else {
//throw new RuntimeException("instance is error") ;
return false;
}
if (UNLOCK_MSG.equals(result)) {
return true;
} else {
return false;
}
}
/**
* read lua script
*/
private void buildScript() {
script = ScriptUtil.getScript("lock.lua");
}
public static class Builder {
private static final String DEFAULT_LOCK_PREFIX = "lock_";
/**
* default sleep time
*/
private static final int DEFAULT_SLEEP_TIME = 100;
private T jedis;
private String lockPrefix = DEFAULT_LOCK_PREFIX;
private int sleepTime = DEFAULT_SLEEP_TIME;
public Builder(T jedis) {
this.jedis = jedis;
}
public Builder lockPrefix(String lockPrefix) {
this.lockPrefix = lockPrefix;
return this;
}
public Builder sleepTime(int sleepTime) {
this.sleepTime = sleepTime;
return this;
}
public RedisLock build() {
return new RedisLock(this);
}
}
}