mitao
2025-03-19 0ab9dfd8f122195e4e9f09bd50c59e0a47450bec
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
@@ -1,16 +1,14 @@
package com.ruoyi.common.core.redis;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
/**
@@ -22,6 +20,15 @@
@Component
public class RedisCache
{
    private static final String LOCK_PREFIX = "lock:";
    private static final RedisScript<Long> UNLOCK_SCRIPT = new DefaultRedisScript<>(
            "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                    "  return redis.call('del', KEYS[1]) " +
                    "else " +
                    "  return 0 " +
                    "end",
            Long.class
    );
    @Autowired
    public RedisTemplate redisTemplate;
@@ -265,4 +272,72 @@
    {
        return redisTemplate.keys(pattern);
    }
    /**
     * 尝试加锁
     *
     * @param lockKey   锁的key
     * @param requestId 锁的持有者标识符(如UUID)
     * @param expireTime 锁的过期时间(秒)
     * @return 加锁成功返回true,否则返回false
     */
    public boolean tryLock(String lockKey, String requestId, long expireTime) {
        String lockKeyWithPrefix = LOCK_PREFIX + lockKey;
        // 使用SET命令的NX和PX选项来加锁
        Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKeyWithPrefix, requestId, expireTime, TimeUnit.SECONDS);
        return result != null && result;
    }
    /**
     * 尝试加锁
     *
     * @param lockKey   锁的key
     * @param requestId 锁的持有者标识符(如UUID)
     * @param expireTime 锁的过期时间(秒)
     * @return 加锁成功返回true,否则返回false
     */
    public boolean trylockLoop(String lockKey, String requestId,long expireTime) {
        String lockKeyWithPrefix = LOCK_PREFIX + lockKey;
        // 使用SET命令的NX和PX选项来加锁
        Boolean result = false;
        int num = 50;
        while (num>0){
            result = redisTemplate.opsForValue().setIfAbsent(lockKeyWithPrefix, requestId, expireTime, TimeUnit.SECONDS);
            if (result){
                break;
            }
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            num--;
        }
        return result;
    }
    /**
     * 解锁
     *
     * @param lockKey   锁的key
     * @param requestId 锁的持有者标识符(如UUID)
     * @return 解锁成功返回true,否则返回false
     */
    public boolean unlock(String lockKey, String requestId) {
        String lockKeyWithPrefix = LOCK_PREFIX + lockKey;
        // 使用Lua脚本来验证锁的持有者并解锁
        Long result = (Long) redisTemplate.execute(UNLOCK_SCRIPT, Collections.singletonList(lockKeyWithPrefix), requestId);
        return result != null && result == 1L;
    }
    /**
     * 自增
     * @param key 要加一的键
     */
    public int increment(String key) {
        // +1 操作
        return redisTemplate.opsForValue().increment(key).intValue();
    }
}