leniu-redis-cache

适用于 leniu-tengyun-core 项目的 Redis 缓存和分布式锁操作。

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "leniu-redis-cache" with this command: npx skills add xu-cell/ai-engineering-init/xu-cell-ai-engineering-init-leniu-redis-cache

leniu-redis-cache

适用于 leniu-tengyun-core 项目的 Redis 缓存和分布式锁操作。

RedisUtil 工具类

位置:net.xnzn.core.common.redis.RedisUtil

String 操作

import net.xnzn.core.common.redis.RedisUtil;

// 设置 String(无过期时间) RedisUtil.setString("key", "value");

// 设置 String(带过期时间,单位秒) RedisUtil.setString("key", "value", 3600L);

// 获取 String String value = RedisUtil.getString("key");

// 存在则更新,不存在则设置 Boolean updated = RedisUtil.setIfPresentString("key", "new-value", 3600L);

Object 操作

// 设置对象(无过期时间) RedisUtil.setObj("user:123", user);

// 设置对象(带过期时间) RedisUtil.setObj("user:123", user, 1800L);

// 获取对象 Object user = RedisUtil.getObj("user:123"); User userObj = (User) RedisUtil.getObj("user:123");

删除操作

// 删除指定 key RedisUtil.delete("user:123");

// 批量删除(匹配模式) RedisUtil.deleteByPattern("cache:user:*");

自增/自减

// 自增(返回递增后的值) Integer count = RedisUtil.incr("counter", 3600L);

// 自减(返回递减后的值) Integer count = RedisUtil.decr("counter", 3600L);

// 仅获取当前值(不增减) Integer current = RedisUtil.getRedisAtomicInteger("counter", null, null);

分布式锁

import org.redisson.api.RLock;

// 获取锁对象 RLock lock = RedisUtil.getLock("lock:order:123");

// 标准用法(推荐):lock() 直接阻塞获取 RLock lock = RedisUtil.getLock("lock:order:123"); lock.lock(); try { // 执行业务逻辑 doBusiness(); } catch (Exception e) { log.error("业务处理异常", e); } finally { // ✅ 安全释放锁:双重检查,防止重复 unlock try { if (lock.isHeldByCurrentThread() && lock.isLocked()) { lock.unlock(); } } catch (Exception e) { log.error("解锁异常", e); } }

// tryLock 用法(不阻塞,失败直接抛异常) RLock lock2 = RedisUtil.getLock("lock:order:123"); if (!lock2.tryLock()) { throw new LeException("订单正在处理中,请稍后重试"); } try { doBusiness(); } finally { try { if (lock2.isHeldByCurrentThread() && lock2.isLocked()) { lock2.unlock(); } } catch (Exception e) { log.error("解锁异常", e); } }

// 检查锁状态 boolean locked = RedisUtil.isLock("lock:order:123");

已弃用的方法(避免代码扫描问题,请使用 getLock

  • lock/unlock ):

// 不推荐使用(已弃用) RedisUtil.tryLock("lock:key", 10, 30); RedisUtil.lock("lock:key"); RedisUtil.unLock("lock:key");

ZSet 操作

// 添加到有序集合 RedisUtil.zAdd("ranking:weekly", "user123", 95.5); RedisUtil.zAdd("ranking:weekly", "user456", 88.3);

// 获取排名数据(带分数) Set<ZSetOperations.TypedTuple<Object>> ranking = RedisUtil.zGetList("ranking:weekly", 0, 9);

// 从有序集合中删除 RedisUtil.zRemove("ranking:weekly", "user123");

批量操作

// 批量保存 Map<String, Object> map = new HashMap<>(); map.put("key1", "value1"); map.put("key2", "value2"); RedisUtil.multiSet(map);

// 批量获取 List keys = Arrays.asList("key1", "key2", "key3"); List values = RedisUtil.multiGet(keys);

Key 查询

// 匹配 key List<String> keys = RedisUtil.keysByPattern("cache:*");

// 检查锁是否锁定 boolean isLocked = RedisUtil.isLock("lock:order:123");

缓存配置

最大缓存时间

可以通过配置限制缓存的最大过期时间:

spring: redis: # 自定义最大缓存时间(秒) custom-max-expiration-second: 86400 # 24小时

缓存 Key 命名规范

类型 命名格式 示例

用户信息 user:{id}

user:12345

用户列表缓存 user:list:{params_hash}

user:list:abc123

权限缓存 permissions:subject_id:{id}

permissions:subject_id:123

角色缓存 roles:subject_id:{id}

roles:subject_id:123

租户配置 tenant:config:{id}

tenant:config:123

字典缓存 dict:{type}:{key}

dict:sys_yes_no:1

分布式锁 lock:{module}:{id}

lock:order:123

限流器 rate:{user_id}:{api}

rate:123:/api/order/create

典型场景

缓存击穿保护

public User getUserById(Long userId) { String key = "user:" + userId;

// 先查缓存
Object cached = RedisUtil.getObj(key);
if (cached != null) {
    return (User) cached;
}

// 使用分布式锁防止缓存击穿
RLock lock = RedisUtil.getLock("lock:user:" + userId);
try {
    if (lock.tryLock(5, 30, TimeUnit.SECONDS)) {
        try {
            // 双重检查
            cached = RedisUtil.getObj(key);
            if (cached != null) {
                return (User) cached;
            }

            // 查询数据库
            User user = userMapper.selectById(userId);
            if (user != null) {
                RedisUtil.setObj(key, user, 3600L);
            }
            return user;
        } finally {
            lock.unlock();
        }
    }
    return userMapper.selectById(userId);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    return userMapper.selectById(userId);
}

}

限流器

public boolean checkRateLimit(Long userId, String api, int limit, int seconds) { String key = String.format("rate:%d:%s", userId, api); Integer count = RedisUtil.incr(key, (long) seconds);

// 首次请求设置过期时间
if (count == 1) {
    RedisUtil.setString(key, count.toString(), (long) seconds);
}

return count &#x3C;= limit;

}

分布式任务去重

public void executeTask(String taskId) { String key = "task:executing:" + taskId;

// setNx 防止重复执行
boolean acquired = RedisUtil.setNx(key, "1", 300);
if (!acquired) {
    log.warn("任务正在执行中: {}", taskId);
    return;
}

try {
    // 执行任务
    doTask(taskId);
} finally {
    RedisUtil.delete(key);
}

}

排行榜

// 添加分数 public void addScore(Long userId, Double score) { RedisUtil.zAdd("ranking:daily", String.valueOf(userId), score); }

// 获取 TOP 10 public List<RankingItem> getTop10() { Set<ZSetOperations.TypedTuple<Object>> ranking = RedisUtil.zGetList("ranking:daily", 0, 9);

return ranking.stream()
    .map(tuple -> new RankingItem(
        Long.parseLong(tuple.getValue().toString()),
        tuple.getScore()
    ))
    .sorted(Comparator.comparing(RankingItem::getScore).reversed())
    .collect(Collectors.toList());

}

// 获取用户排名 public Long getUserRank(Long userId) { // 需要 RedisUtil 扩展,或使用 RedisTemplate Long rank = redisTemplate.opsForZSet().rank("ranking:daily", String.valueOf(userId)); return rank != null ? rank + 1 : null; }

与 RuoYi-Plus 的区别

特性 RuoYi-Plus leniu-tengyun-core

工具类 RedisUtils

RedisUtil

分布式锁 RedisUtils.lock()

RedisUtil.getLock()

设置对象 RedisUtils.setCacheObject()

RedisUtil.setObj()

获取对象 RedisUtils.getCacheObject()

RedisUtil.getObj()

删除 RedisUtils.deleteObject()

RedisUtil.delete()

ZSet 操作 RedisUtils.getCacheZSetRank()

RedisUtil.zAdd/zGetList()

缓存注解 @Cacheable

未使用注解方式

锁释放 RedisUtils.unlock()

RLock.unlock()

注意事项

  • setNx 用于防止重复执行,返回 true 表示设置成功

  • 分布式锁必须使用 try-finally 确保 unlock 执行

  • 自增/自减操作可指定过期时间,首次自增时设置

  • 过期时间单位统一为秒

  • 批量删除使用 deleteByPattern 会扫描所有匹配 key,生产环境慎用

  • RedisUtil 底层使用 RedisTemplate 和 RedissonClient

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

scheduled-jobs

No summary provided by upstream source.

Repository SourceNeeds Review
General

loki-log-query

No summary provided by upstream source.

Repository SourceNeeds Review
General

file-oss-management

No summary provided by upstream source.

Repository SourceNeeds Review
General

progress

No summary provided by upstream source.

Repository SourceNeeds Review