跳到主要内容

RedisUtils API 参考

RedisUtils 是项目封装的 Redis 通用工具类,基于 RedisTemplate 提供类型安全、参数校验、日志记录的便捷操作。

位置: blog-common/src/main/java/com/blog/common/utils/RedisUtils.java


🎯 核心特性

特性说明
参数校验使用 Guava Preconditions,防止空值和非法参数
日志记录SLF4J 参数化日志,便于问题排查
类型安全Optional 包装返回值,避免空指针
批量操作支持 MGET/MSET,减少网络往返
防雪崩setWithRandomTTL 支持随机 TTL

📖 通用操作

hasKey

判断 key 是否存在

boolean exists = redisUtils.hasKey("user:123");
参数类型说明
keyString键(非空)
返回boolean存在返回 true

expire

设置过期时间

redisUtils.expire("user:123", 30, TimeUnit.MINUTES);
参数类型说明
keyString
timeoutlong过期时间(> 0)
unitTimeUnit时间单位
返回boolean设置成功返回 true

delete

删除键

// 删除单个
redisUtils.delete("user:123");

// 批量删除
redisUtils.delete(List.of("user:1", "user:2", "user:3"));
参数类型说明
key / keysString / Collection要删除的键
返回boolean / Long是否成功 / 删除数量

📝 String 操作

set

设置值

// 永不过期(不推荐)
redisUtils.set("key", value);

// 带过期时间(推荐)
redisUtils.set("key", value, 30, TimeUnit.MINUTES);
参数类型说明
keyString
valueObject值(非空)
timeoutlong过期时间(可选)
unitTimeUnit时间单位(可选)

setIfAbsent

只有 key 不存在时才设置(分布式锁

boolean locked = redisUtils.setIfAbsent(
"lock:order:123",
"locked",
10,
TimeUnit.SECONDS
);

if (locked) {
try {
// 执行临界区代码
} finally {
redisUtils.delete("lock:order:123");
}
}
参数类型说明
keyString锁键
valueObject锁值
timeoutlong锁超时时间
unitTimeUnit时间单位
返回booleantrue=获取锁成功
分布式锁

这是实现简单分布式锁的核心方法,对应 Redis 的 SET NX EX 命令。


get

获取值

// 基础获取(返回 Object)
Object value = redisUtils.get("key");

// 类型安全获取
UserDTO user = redisUtils.get("user:123", UserDTO.class);

// Optional 包装(推荐)
Optional<UserDTO> userOpt = redisUtils.getOptional("user:123", UserDTO.class);
userOpt.ifPresent(u -> System.out.println(u.getUsername()));
方法返回类型说明
get(key)Object可能为 null
get(key, clazz)T类型转换,可能为 null
getOptional(key, clazz)Optional<T>避免 null,推荐使用

increment / decrement

原子计数器

// 递增(文章浏览量)
Long views = redisUtils.increment("article:views:123");

// 递减(库存扣减)
Long stock = redisUtils.decrement("product:stock:456");
方法返回说明
increment(key)Long递增后的值
decrement(key)Long递减后的值

🗂️ Hash 操作

hSet / hGet

单个字段操作

// 设置字段
redisUtils.hSet("user:123", "name", "张三");
redisUtils.hSet("user:123", "age", 25);

// 获取字段
Object name = redisUtils.hGet("user:123", "name"); // "张三"

hSetAll / hGetAll

批量操作

// 批量设置
Map<String, Object> userMap = Map.of(
"name", "张三",
"age", 25,
"email", "zhangsan@example.com"
);
redisUtils.hSetAll("user:123", userMap);

// 批量获取
Map<Object, Object> result = redisUtils.hGetAll("user:123");

hDel

删除字段

Long deleted = redisUtils.hDel("user:123", "age", "email");
// deleted = 2

📦 Set 操作

sAdd / sMembers

// 添加元素(自动去重)
redisUtils.sAdd("user:123:tags", "java", "spring", "redis");

// 获取所有元素
Set<Object> tags = redisUtils.sMembers("user:123:tags");
// ["java", "spring", "redis"]

使用场景:标签、关注列表、点赞用户集合


📋 List 操作

lPush / rPop

队列操作

// 从左侧推入(入队)
redisUtils.lPush("task:queue", task1);
redisUtils.lPush("task:queue", task2);

// 从右侧弹出(出队)
Object task = redisUtils.rPop("task:queue");

使用场景:消息队列、任务队列


lRange / lSize

// 获取范围元素(0 到 -1 表示全部)
List<Object> tasks = redisUtils.lRange("task:queue", 0, -1);

// 获取列表长度
Long size = redisUtils.lSize("task:queue");

⚡ 批量操作

mGet

批量获取(性能优化

List<String> keys = List.of("user:1", "user:2", "user:3");
List<Object> values = redisUtils.mGet(keys);
// 顺序与 keys 一致,不存在的键对应 null
性能对比
单次获取:3 次网络请求
批量获取:1 次网络请求(节省 2 次 RTT)

mSet

批量设置

Map<String, Object> data = Map.of(
"config:a", "value1",
"config:b", "value2",
"config:c", "value3"
);
redisUtils.mSet(data);

限制:批量操作最多 100 个键,防止慢查询。


🛡️ 高级操作

setWithRandomTTL

防缓存雪崩

redisUtils.setWithRandomTTL(
"article:123",
article,
30, // 基础 TTL: 30 分钟
TimeUnit.MINUTES,
10 // 随机偏移: ±10%
);
// 实际 TTL 范围:27~33 分钟
参数类型说明
keyString
valueObject
baseTimeoutlong基础过期时间
unitTimeUnit时间单位
randomPercentint随机百分比(0-100)

原理:在基础 TTL 上添加随机偏移,避免大量缓存同时过期导致数据库压力骤增。


📊 使用场景汇总

场景方法示例
用户信息缓存set + getset("user:123", user, 30, MINUTES)
分布式锁setIfAbsentsetIfAbsent("lock:xxx", "1", 10, SECONDS)
浏览量计数incrementincrement("article:views:123")
用户属性hSet + hGethSet("user:123", "name", "张三")
标签集合sAdd + sMemberssAdd("tags:123", "java", "spring")
任务队列lPush + rPoplPush("queue", task)
批量查询mGetmGet(List.of("user:1", "user:2"))
防雪崩setWithRandomTTL见上文

⚠️ 注意事项

1. 总是设置 TTL

// ❌ 不推荐
redisUtils.set("key", value);

// ✅ 推荐
redisUtils.set("key", value, 30, TimeUnit.MINUTES);

2. 批量操作有限制

// ❌ 超过限制会抛异常
redisUtils.mGet(hugeListWith200Keys); // IllegalArgumentException

// ✅ 分批处理
Lists.partition(allKeys, 100).forEach(batch -> {
redisUtils.mGet(batch);
});

3. 使用 Optional 避免 NPE

// ❌ 可能 NPE
UserDTO user = redisUtils.get("user:123", UserDTO.class);
user.getUsername(); // 如果 user 为 null?

// ✅ 安全
redisUtils.getOptional("user:123", UserDTO.class)
.ifPresent(u -> System.out.println(u.getUsername()));

📚 延伸阅读