@Component @Slf4j public class LockUtil { @Autowired private StringRedisTemplate redisTemplate; public boolean tryLock(String key, String value, Long expireTime) { return Boolean.TRUE.equals(redisTemplate.opsForValue() .setIfAbsent(key, value, expireTime, TimeUnit.SECONDS)); } public void unLock(String key, String value) { String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" + " return redis.call(\"del\",KEYS[1])\n" + "else\n" + " return 0\n" + "end"; // 1 成功 Long res = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Collections.singletonList(key), value); if (res == null || res == 0) { String realValue = redisTemplate.opsForValue().get(key); log.error("解锁失败,key:{}, value:{}, realValue:{}", key, value, realValue); } } /** * 加锁 * * @param keyname 锁的标识名 * @param timeoutMs 循环获取锁的等待超时时间(毫秒),在此时间内会一直尝试获取锁直到超时,为0表示失败后直接返回不等待 * @param expireMs 当前锁的最大生存时间(毫秒),必须大于0,如果超过生存时间锁仍未被释放,则系统会自动强制释放 * @param waitIntervalMs 获取锁失败后挂起再试的时间间隔(毫秒) * @return [type] [description] */ public long loopLock(String keyname, String value, long timeoutMs, long expireMs, long waitIntervalMs) { if (keyname == null || keyname.trim().length() == 0) { return 0; } log.info("loopLock keyname:【{}】,timeout【{}ms】,expire【{}ms】,waitInterval【{}ms】", keyname, timeoutMs, expireMs, waitIntervalMs); long timeoutAt = System.currentTimeMillis(); if (timeoutMs > 0) { timeoutAt = timeoutAt + timeoutMs; } long times = 0; while (true) { long now = System.currentTimeMillis(); long expireAt = now + expireMs; String statusCode = setLock(keyname, value, expireMs); if ("OK".equals(statusCode)) { log.info("keyname:【{}】success.", keyname); return expireAt; } if (timeoutMs <= 0 || timeoutAt < now) { log.info("keyname:【{}】fail.", keyname); return 0; } try { Thread.sleep(waitIntervalMs); } catch (Exception e) { log.error("Thread.sleep error", e.getMessage(), e); } log.info("keyname:【{}】,times of:【{}】.", keyname, ++times); } } public String setLock(String key, String value, long expire) { Boolean success = redisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofMillis(expire)); return Boolean.TRUE.equals(success) ? "OK" : "FAIL"; } /** * 获取缓存的String值 * @author hongjian.chen * @date 2023/3/17 19:28 * @param key key名称 * @return java.lang.String **/ public String getString(String key) { return redisTemplate.opsForValue().get(key); } }
使用redis加锁工具类
于 2023-06-07 10:28:42 首次发布