使用redis加锁工具类

@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,java,数据库,缓存)