超强Redis工具类:集成分布式锁+限流+事务,一行代码搞定复杂操作!

工具类核心功能

  1. ​分布式锁全家桶
    ✅ 可重入锁支持
    ✅ 自动续期/超时释放
    ✅ 锁竞争等待策略
    ✅ 锁状态实时监控
// 示例:电商库存扣减场景
String lockKey = "stock_lock:" + productId;
if (RedisUtils.tryLock(lockKey, 1000, 30000)) {
    try {
        // 执行库存扣减逻辑
    } finally {
        RedisUtils.unlock(lockKey);
    }
}
  1. ​精细化限流控制
    支持全局限流/单机限流
    令牌桶算法实现
    实时返回剩余令牌数
// 示例:接口限流(每秒10次)
long permits = RedisUtils.rateLimiter(
    "api_limit:login", 
    RateType.OVERALL, 
    10, 1
);
if (permits == -1) throw new RuntimeException("请求过于频繁");
  1. ​发布订阅增强版
// 发布订单创建消息
RedisUtils.publish("order:created", orderDTO, msg -> {
    log.info("消息已送达:{}", msg.getId());
});

// 订阅订单消息
RedisUtils.subscribe("order:created", OrderDTO.class, msg -> {
    // 处理订单消息
});

快速接入指南

  1. 添加Maven依赖
<dependency>
    <groupId>org.redissongroupId>
    <artifactId>redisson-spring-boot-starterartifactId>
    <version>3.21.0version>
dependency>
  1. 核心配置(application.yml)
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    # 集群模式配置示例
    # cluster:
    #   nodes: 192.168.0.1:7000,192.168.0.2:7001

⚠️ 关键注意事项 - 分布式锁必须成对使用

// 错误示例(缺少try-finally)
if (RedisUtils.tryLock(lockKey)) {
    // 业务代码
    RedisUtils.unlock(lockKey); // 可能无法执行
}

完整工具代码

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.redisson.api.options.KeysScanOptions;

import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Redis 工具类
 *
 * @author Devil
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RedisUtils {

    private static final RedissonClient CLIENT = SpringUtil.getBean(RedissonClient.class);

    /* ---------------------- 分布式锁操作 ---------------------- */

    /**
     * 执行带锁的操作(自动释放)
     *
     * @param lockKey   锁名称
     * @param waitTime  等待时间(秒)
     * @param leaseTime 持有时间(秒)
     * @param action    业务逻辑
     */
    public static void executeWithLock(String lockKey, long waitTime, long leaseTime, Runnable action) {
        RLock lock = getLock(lockKey);
        try {
            if (lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS)) {
                action.run();
            } else {
                log.error("Redis Acquisition lock timeout, key: {}", lockKey);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Redis Lock acquisition interrupt, key: {}", lockKey, e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 快速执行带锁操作(默认等待3秒,自动续期)
     *
     * @param lockKey 锁名称
     * @param action  业务逻辑
     */
    public static void executeWithLock(String lockKey, Runnable action) {
        executeWithLock(lockKey, 3, -1, action);
    }

    /**
     * 获取分布式锁对象
     *
     * @param lockKey 锁键名
     * @return RLock 锁对象
     */
    public static RLock getLock(String lockKey) {
        return CLIENT.getLock(lockKey);
    }

    /**
     * 尝试获取锁(立即返回结果)
     *
     * @param lockKey 锁键名
     * @return 是否获取成功
     */
    public static boolean tryLock(String lockKey) {
        RLock lock = getLock(lockKey);
        try {
            return lock.tryLock();
        } catch (Exception e) {
            log.error("Redis lock error, key: {}", lockKey, e);
            return false;
        }
    }

    /**
     * 尝试获取锁(指定等待时间和持有时间)
     *
     * @param lockKey   锁键名
     * @param waitTime  等待时间(毫秒)
     * @param leaseTime 持有时间(毫秒)
     * @return 是否获取成功
     */
    public static boolean tryLock(String lockKey, long waitTime, long leaseTime) {
        RLock lock = getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("Redis lock interrupted, key: {}", lockKey, e);
            return false;
        } catch (Exception e) {
            log.error("Redis lock error, key: {}", lockKey, e);
            return false;
        }
    }

    /**
     * 释放分布式锁
     *
     * @param lockKey 锁键名
     */
    public static void unlock(String lockKey) {
        RLock lock = getLock(lockKey);
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            try {
                lock.unlock();
            } catch (IllegalMonitorStateException e) {
                log.error("Redis unlock error: lock not held by current thread, key: {}", lockKey);
            }
        }
    }

    /**
     * 强制释放分布式锁(慎用)
     *
     * @param lockKey 锁键名
     */
    public static void forceUnlock(String lockKey) {
        RLock lock = getLock(lockKey);
        if (lock.isLocked()) {
            lock.forceUnlock();
        }
    }

    /**
     * 检查锁是否被任意线程持有
     *
     * @param lockKey 锁键名
     * @return 是否被锁定
     */
    public static boolean isLocked(String lockKey) {
        return getLock(lockKey).isLocked();
    }

    /* ---------------------- 限流操作 ---------------------- */

    /**
     * 限流操作
     *
     * @param key          限流键名
     * @param rateType     限流类型
     * @param rate         速率(单位时间内允许的请求数)
     * @param rateInterval 速率间隔(秒)
     * @return 剩余许可数(-1 表示限流)
     */
    public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval) {
        return rateLimiter(key, rateType, rate, rateInterval, 0);
    }

    /**
     * 带超时时间的限流操作
     *
     * @param key          限流键名
     * @param rateType     限流类型
     * @param rate         速率
     * @param rateInterval 速率间隔(秒)
     * @param timeout      超时时间(秒)
     * @return 剩余许可数(-1 表示限流)
     */
    public static long rateLimiter(String key, RateType rateType, int rate, int rateInterval, int timeout) {
        validateKey(key);
        RRateLimiter rateLimiter = CLIENT.getRateLimiter(key);
        try {
            rateLimiter.trySetRate(rateType, rate, Duration.ofSeconds(rateInterval), Duration.ofSeconds(timeout));
            if (rateLimiter.tryAcquire()) {
                return rateLimiter.availablePermits();
            }
        } catch (Exception e) {
            log.error("Redis rate limiter error, key: {}", key, e);
        }
        return -1L;
    }

    /* ---------------------- 发布订阅 ---------------------- */

    /**
     * 发布消息到指定频道(带回调)
     */
    public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
        validateKey(channelKey);
        try {
            RTopic topic = CLIENT.getTopic(channelKey);
            long receivers = topic.publish(msg);
            log.debug("Message published to {} channels, key: {}", receivers, channelKey);
            consumer.accept(msg);
        } catch (Exception e) {
            log.error("Redis publish error, key: {}", channelKey, e);
        }
    }

    /**
     * 发布消息到指定频道
     */
    public static <T> void publish(String channelKey, T msg) {
        publish(channelKey, msg, t -> {
        });
    }

    /**
     * 订阅指定频道的消息
     */
    public static <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
        validateKey(channelKey);
        RTopic topic = CLIENT.getTopic(channelKey);
        topic.addListener(clazz, (channel, msg) -> {
            log.debug("Message received from channel: {}", channel);
            consumer.accept(msg);
        });
    }

    /* ---------------------- 键值操作 ---------------------- */

    /**
     * 缓存基本对象(永久有效)
     */
    public static <T> void setCacheObject(String key, T value) {
        setCacheObject(key, value, false, null);
    }

    /**
     * 缓存基本对象(可保留TTL)
     */
    public static <T> void setCacheObject(String key, T value, boolean keepTTL) {
        setCacheObject(key, value, keepTTL, null);
    }

    /**
     * 缓存基本对象(指定有效期)
     */
    public static <T> void setCacheObject(String key, T value, Duration duration) {
        setCacheObject(key, value, false, duration);
    }

    private static <T> void setCacheObject(String key, T value, boolean keepTTL, Duration duration) {
        validateKeyValue(key, value);
        RBucket<T> bucket = CLIENT.getBucket(key);
        try {
            if (keepTTL) {
                bucket.setAndKeepTTL(value);
            } else if (duration != null) {
                bucket.set(value, duration);
            } else {
                bucket.set(value);
            }
        } catch (Exception e) {
            log.error("Redis set cache error, key: {}", key, e);
        }
    }

    /**
     * 安全获取缓存对象
     */
    public static <T> T getCacheObject(String key) {
        validateKey(key);
        try {
            RBucket<T> bucket = CLIENT.getBucket(key);
            return bucket.get();
        } catch (Exception e) {
            log.error("Redis get cache error, key: {}", key, e);
            return null;
        }
    }

    /**
     * 设置有效时间
     */
    public static boolean expire(String key, Duration duration) {
        validateKey(key);
        RBucket<Object> rBucket = CLIENT.getBucket(key);
        try {
            return rBucket.expire(duration);
        } catch (Exception e) {
            log.error("Redis expire error, key: {}", key, e);
            return false;
        }
    }

    /**
     * 删除单个对象
     */
    public static boolean deleteObject(String key) {
        validateKey(key);
        try {
            return CLIENT.getBucket(key).delete();
        } catch (Exception e) {
            log.error("Redis delete error, key: {}", key, e);
            return false;
        }
    }

    /**
     * 批量删除键
     */
    public static long deleteKeys(String... keys) {
        if (keys == null || keys.length == 0) return 0;
        try {
            return CLIENT.getKeys().delete(keys);
        } catch (Exception e) {
            log.error("Redis delete keys error", e);
            return 0;
        }
    }

    /**
     * 检查缓存对象是否存在
     */
    public static boolean isExistsObject(String key) {
        validateKey(key);
        try {
            return CLIENT.getBucket(key).isExists();
        } catch (Exception e) {
            log.error("Redis exists check error, key: {}", key, e);
            return false;
        }
    }

    /* ---------------------- 列表操作 ---------------------- */

    /**
     * 缓存List数据
     */
    public static <T> boolean setCacheList(String key, List<T> dataList) {
        validateKeyValue(key, dataList);
        RList<T> rList = CLIENT.getList(key);
        try {
            return rList.addAll(dataList);
        } catch (Exception e) {
            log.error("Redis set list error, key: {}", key, e);
            return false;
        }
    }

    /**
     * 获取缓存列表
     */
    public static <T> List<T> getCacheList(String key) {
        validateKey(key);
        RList<T> rList = CLIENT.getList(key);
        try {
            return rList.readAll();
        } catch (Exception e) {
            log.error("Redis get list error, key: {}", key, e);
            return null;
        }
    }

    /* ---------------------- 集合操作 ---------------------- */

    /**
     * 缓存Set数据
     */
    public static <T> boolean setCacheSet(String key, Set<T> dataSet) {
        validateKeyValue(key, dataSet);
        RSet<T> rSet = CLIENT.getSet(key);
        try {
            return rSet.addAll(dataSet);
        } catch (Exception e) {
            log.error("Redis set error, key: {}", key, e);
            return false;
        }
    }

    /**
     * 获取缓存集合
     */
    public static <T> Set<T> getCacheSet(String key) {
        validateKey(key);
        RSet<T> rSet = CLIENT.getSet(key);
        try {
            return rSet.readAll();
        } catch (Exception e) {
            log.error("Redis get set error, key: {}", key, e);
            return null;
        }
    }

    /* ---------------------- 哈希操作 ---------------------- */

    /**
     * 缓存Map数据
     */
    public static <T> void setCacheMap(String key, Map<String, T> dataMap) {
        validateKeyValue(key, dataMap);
        RMap<String, T> rMap = CLIENT.getMap(key);
        try {
            rMap.putAll(dataMap);
        } catch (Exception e) {
            log.error("Redis set map error, key: {}", key, e);
        }
    }

    /**
     * 获取缓存Map
     */
    public static <T> Map<String, T> getCacheMap(String key) {
        validateKey(key);
        RMap<String, T> rMap = CLIENT.getMap(key);
        try {
            return rMap.getAll(rMap.keySet());
        } catch (Exception e) {
            log.error("Redis get map error, key: {}", key, e);
            return null;
        }
    }

    /* ---------------------- 原子操作 ---------------------- */

    /**
     * 设置原子值
     */
    public static void setAtomicValue(String key, long value) {
        validateKey(key);
        RAtomicLong atomic = CLIENT.getAtomicLong(key);
        try {
            atomic.set(value);
        } catch (Exception e) {
            log.error("Redis set atomic error, key: {}", key, e);
        }
    }

    /**
     * 递增原子值
     */
    public static long incrAtomicValue(String key) {
        validateKey(key);
        RAtomicLong atomic = CLIENT.getAtomicLong(key);
        try {
            return atomic.incrementAndGet();
        } catch (Exception e) {
            log.error("Redis incr atomic error, key: {}", key, e);
            return -1;
        }
    }

    /**
     * 递减原子值
     */
    public static long decrementAndGet(String key) {
        validateKey(key);
        RAtomicLong atomic = CLIENT.getAtomicLong(key);
        try {
            return atomic.decrementAndGet();
        } catch (Exception e) {
            log.error("Redis decr atomic error, key: {}", key, e);
            return -1;
        }
    }

    /* ---------------------- 工具方法 ---------------------- */

    private static void validateKey(String key) {
        if (StrUtil.isBlank(key)) {
            throw new IllegalArgumentException("Redis key cannot be blank");
        }
    }

    private static <T> void validateKeyValue(String key, T value) {
        validateKey(key);
        if (value == null) {
            throw new IllegalArgumentException("Redis value cannot be null");
        }
    }

    /**
     * 事务执行模板
     */
    public static void executeInTransaction(Consumer<RBatch> action) {
        RBatch batch = CLIENT.createBatch(BatchOptions.defaults().executionMode(BatchOptions.ExecutionMode.IN_MEMORY_ATOMIC));
        try {
            action.accept(batch);
            batch.execute();
        } catch (Exception e) {
            log.error("Redis transaction error", e);
            batch.discard();
        }
    }

    /**
     * 扫描键集合
     */
    public static Collection<String> keys(KeysScanOptions keysScanOptions) {
        try {
            Stream<String> keysStream = CLIENT.getKeys().getKeysStream(keysScanOptions);
            return keysStream.collect(Collectors.toList());
        } catch (Exception e) {
            log.error("Redis keys scan error", e);
            return null;
        }
    }

    /**
     * 获取Redisson客户端实例
     */
    public static RedissonClient getClient() {
        return CLIENT;
    }
}

你可能感兴趣的:(Java,Redis,分布式,redis,分布式,数据库)