|
@@ -1,122 +0,0 @@
|
|
|
-package net.yyc.quartz.util;
|
|
|
|
|
-
|
|
|
|
|
-import com.google.common.collect.Lists;
|
|
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
-import org.springframework.data.redis.core.RedisTemplate;
|
|
|
|
|
-import org.springframework.data.redis.core.script.DefaultRedisScript;
|
|
|
|
|
-import org.springframework.util.Assert;
|
|
|
|
|
-import org.springframework.util.StringUtils;
|
|
|
|
|
-
|
|
|
|
|
-import java.time.Duration;
|
|
|
|
|
-import java.util.Objects;
|
|
|
|
|
-import java.util.Random;
|
|
|
|
|
-import java.util.UUID;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * Redis 分布式锁(与 upms-biz {@code com.qunzhixinxi.hnqz.admin.util.RedisLock} 行为一致,供 quartz 使用同一 Redis 互斥)
|
|
|
|
|
- */
|
|
|
|
|
-@Slf4j
|
|
|
|
|
-public class RedisLock {
|
|
|
|
|
-
|
|
|
|
|
- private final RedisTemplate redisTemplate;
|
|
|
|
|
-
|
|
|
|
|
- private static final DefaultRedisScript<Long> UNLOCK_LUA;
|
|
|
|
|
-
|
|
|
|
|
- static {
|
|
|
|
|
- StringBuilder script = new StringBuilder();
|
|
|
|
|
- script.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] ");
|
|
|
|
|
- script.append("then ");
|
|
|
|
|
- script.append(" return redis.call(\"del\",KEYS[1]) ");
|
|
|
|
|
- script.append("else ");
|
|
|
|
|
- script.append(" return 0 ");
|
|
|
|
|
- script.append("end ");
|
|
|
|
|
- UNLOCK_LUA = new DefaultRedisScript<>();
|
|
|
|
|
- UNLOCK_LUA.setResultType(Long.class);
|
|
|
|
|
- UNLOCK_LUA.setScriptText(script.toString());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private String lockKey;
|
|
|
|
|
- private String lockValue;
|
|
|
|
|
- private int expireTime = 60;
|
|
|
|
|
- private long timeOut = 100;
|
|
|
|
|
- private volatile boolean locked = false;
|
|
|
|
|
- private final Random random = new Random();
|
|
|
|
|
-
|
|
|
|
|
- public RedisLock(RedisTemplate redisTemplate, String lockKey) {
|
|
|
|
|
- this.redisTemplate = redisTemplate;
|
|
|
|
|
- this.lockKey = lockKey + "_lock";
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public RedisLock(RedisTemplate redisTemplate, String lockKey, int expireTime) {
|
|
|
|
|
- this(redisTemplate, lockKey);
|
|
|
|
|
- this.expireTime = expireTime;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public RedisLock(RedisTemplate redisTemplate, String lockKey, long timeOut) {
|
|
|
|
|
- this(redisTemplate, lockKey);
|
|
|
|
|
- this.timeOut = timeOut;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public RedisLock(RedisTemplate<? extends Object, ? extends Object> redisTemplate, String lockKey, int expireTime, long timeOut) {
|
|
|
|
|
- this(redisTemplate, lockKey, expireTime);
|
|
|
|
|
- this.timeOut = timeOut;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public boolean tryLock() {
|
|
|
|
|
- lockValue = UUID.randomUUID().toString();
|
|
|
|
|
- long timeout = timeOut * 1000000;
|
|
|
|
|
- long nowTime = System.nanoTime();
|
|
|
|
|
- while ((System.nanoTime() - nowTime) < timeout) {
|
|
|
|
|
- if (this.set(lockKey, lockValue, expireTime)) {
|
|
|
|
|
- locked = true;
|
|
|
|
|
- return locked;
|
|
|
|
|
- }
|
|
|
|
|
- this.sleep(10, 50000);
|
|
|
|
|
- }
|
|
|
|
|
- return locked;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public boolean lock() {
|
|
|
|
|
- lockValue = UUID.randomUUID().toString();
|
|
|
|
|
- locked = this.set(lockKey, lockValue, expireTime);
|
|
|
|
|
- return locked;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public boolean lockBlock() {
|
|
|
|
|
- lockValue = UUID.randomUUID().toString();
|
|
|
|
|
- while (true) {
|
|
|
|
|
- if (this.set(lockKey, lockValue, expireTime)) {
|
|
|
|
|
- locked = true;
|
|
|
|
|
- return locked;
|
|
|
|
|
- }
|
|
|
|
|
- this.sleep(10, 50000);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public boolean unlock() {
|
|
|
|
|
- if (locked) {
|
|
|
|
|
- Long ret = (Long) redisTemplate.execute(UNLOCK_LUA, Lists.newArrayList(lockKey), lockValue);
|
|
|
|
|
- boolean success = Objects.equals(1L, ret);
|
|
|
|
|
- locked = !success;
|
|
|
|
|
- return success;
|
|
|
|
|
- }
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private boolean set(final String key, final String value, final long seconds) {
|
|
|
|
|
- Assert.isTrue(!StringUtils.isEmpty(key), "key不能为空");
|
|
|
|
|
- boolean ret = Objects.equals(true, redisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofSeconds(seconds)));
|
|
|
|
|
- if (ret) {
|
|
|
|
|
- log.info("获取锁{}的时间:{}", key, System.currentTimeMillis());
|
|
|
|
|
- }
|
|
|
|
|
- return ret;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void sleep(long millis, int nanos) {
|
|
|
|
|
- try {
|
|
|
|
|
- Thread.sleep(millis, random.nextInt(nanos));
|
|
|
|
|
- } catch (InterruptedException e) {
|
|
|
|
|
- log.info("获取分布式锁休眠被中断:", e);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|