sping boot 中使用 redis 分布式锁

public class RedisLock {
private static Logger logger = LoggerFactory.getLogger(RedisLock.class);

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 JedisTemplate jedisTemplate;

/**
 * time millisecond
 */
private static final int TIME = 1000;

/**
 * lua script
 */
private String script;

private RedisLock(Builder builder) {
    this.jedisTemplate = builder.jedisTemplate;
    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(final String key, final String request) {
    String result = set(lockPrefix + key, request, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, 10 * TIME);
    if (LOCK_MSG.equals(result)) {
        return true;
    } else {
        return false;
    }
}

/**
 * jedis 方法
 *
 * @param key
 * @param value
 * @param nxxx
 * @param expx
 * @param time
 * @return
 */
private String set(final String key, final String value, final String nxxx, final String expx,
                   final int time) {
    return jedisTemplate.execute(new Function<Jedis, String>() {
        @Override
        public String apply(Jedis jedis) {
            return jedis.set(key, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, time * TIME);
        }
    });

}

/**
 * blocking lock
 *
 * @param key
 * @param request
 */
public void lock(String key, String request) throws InterruptedException {
    //get connection
    String result;
    for (; ; ) {
        result = 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 {
    String result;
    while (blockTime >= 0) {
        result = 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) {
    //get connection
    String result;
    result = 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;
    result = eval(script, Collections.singletonList(lockPrefix + key), Collections.singletonList(request));

    if (UNLOCK_MSG.equals(result)) {
        return true;
    } else {
        return false;
    }
}

/**
 * redis eval 方法
 *
 * @param script
 * @param keys
 * @param args
 * @return
 */
private Object eval(final String script, final List<String> keys, final List<String> args) {
    return jedisTemplate.execute(new Function<Jedis, Object>() {

        @Override
        public Object apply(Jedis jedis) {
            return jedis.eval(script, keys, args);
        }
    });
}


/**
 * read lua script
 */
private void buildScript() {
    try {
        script = FileUtil.readString(new ClassPathResource("lock.lua").getURL(), CharsetUtil.UTF_8);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}


public static class Builder {
    private static final String DEFAULT_LOCK_PREFIX = "lock_";
    /**
     * default sleep time
     */
    private static final int DEFAULT_SLEEP_TIME = 100;

    private JedisTemplate jedisTemplate = null;


    private String lockPrefix = DEFAULT_LOCK_PREFIX;
    private int sleepTime = DEFAULT_SLEEP_TIME;

    public Builder(JedisTemplate jedisTemplate) {
        this.jedisTemplate = jedisTemplate;
    }

    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);
    }

}

}

lock.lua

if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
else
    return 0
end

猜你喜欢

转载自blog.csdn.net/taotoxht/article/details/82706043