1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
| @Service @Slf4j public class DistributedLockService { @Autowired private RedisTemplate<String, Object> redisTemplate; private static final String LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then " + "return redis.call('del', KEYS[1]) " + "else " + "return 0 " + "end"; private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then " + "return redis.call('del', KEYS[1]) " + "else " + "return 0 " + "end";
public boolean tryLock(String lockKey, String lockValue, long expireTime, TimeUnit timeUnit) { try { Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, expireTime, timeUnit); return success != null && success; } catch (Exception e) { log.error("获取锁失败: lockKey={}", lockKey, e); return false; } }
public boolean lock(String lockKey, String lockValue, long expireTime, TimeUnit timeUnit) { return lock(lockKey, lockValue, expireTime, timeUnit, 30, TimeUnit.SECONDS); }
public boolean lock(String lockKey, String lockValue, long expireTime, TimeUnit timeUnit, long waitTime, TimeUnit waitTimeUnit) { long startTime = System.currentTimeMillis(); long waitTimeMillis = waitTimeUnit.toMillis(waitTime); while (System.currentTimeMillis() - startTime < waitTimeMillis) { if (tryLock(lockKey, lockValue, expireTime, timeUnit)) { return true; } try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } return false; }
public boolean releaseLock(String lockKey, String lockValue) { try { DefaultRedisScript<Long> script = new DefaultRedisScript<>(); script.setScriptText(UNLOCK_SCRIPT); script.setResultType(Long.class); Long result = redisTemplate.execute(script, Collections.singletonList(lockKey), lockValue); return result != null && result == 1; } catch (Exception e) { log.error("释放锁失败: lockKey={}", lockKey, e); return false; } }
public boolean renewLock(String lockKey, String lockValue, long expireTime, TimeUnit timeUnit) { try { String currentValue = (String) redisTemplate.opsForValue().get(lockKey); if (lockValue.equals(currentValue)) { redisTemplate.expire(lockKey, expireTime, timeUnit); return true; } return false; } catch (Exception e) { log.error("续期锁失败: lockKey={}", lockKey, e); return false; } } }
@Component @Slf4j public class ReentrantDistributedLock { @Autowired private RedisTemplate<String, Object> redisTemplate; private final ThreadLocal<Map<String, Integer>> lockCount = new ThreadLocal<>();
public boolean lock(String lockKey, String lockValue, long expireTime, TimeUnit timeUnit) { Map<String, Integer> countMap = lockCount.get(); if (countMap == null) { countMap = new HashMap<>(); lockCount.set(countMap); } Integer count = countMap.get(lockKey); if (count != null && count > 0) { countMap.put(lockKey, count + 1); return true; } Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, expireTime, timeUnit); if (success != null && success) { countMap.put(lockKey, 1); return true; } return false; }
public boolean unlock(String lockKey, String lockValue) { Map<String, Integer> countMap = lockCount.get(); if (countMap == null) { return false; } Integer count = countMap.get(lockKey); if (count == null || count <= 0) { return false; } if (count > 1) { countMap.put(lockKey, count - 1); return true; } String currentValue = (String) redisTemplate.opsForValue().get(lockKey); if (lockValue.equals(currentValue)) { redisTemplate.delete(lockKey); countMap.remove(lockKey); return true; } return false; } }
|