作者:ChenZhen
博客地址:https://www.chenzhen.space/
版权:本文为博主 ChenZhen 的原创文章,本文版权归作者所有,转载请附上原文出处链接及本声明。
如果对你有帮助,请给一个小小的star⭐
进入 Redis 客户端
首先,确保 Redis 服务已经启动。可以使用以下命令进入 Redis 客户端(前提是 Redis 已经安装且正在运行):
redis-cli
远程连接:如果 Redis 服务器在远程主机上,你可以使用 -h 和 -p 指定 IP 地址和端口:
redis-cli -h 192.168.1.100 -p 6379
如果 Redis 设置了密码,还需要加上 -a 参数:
redis-cli -h 192.168.1.100 -p 6379 -a yourpassword
1. Redis键 (key) 操作
-
keys *查看当前库所有 key(匹配:keys *1) -
exists key判断某个 key 是否存在 -
type key查看你的 key 是什么类型 -
del key删除指定的 key 数据 -
unlink key根据 value 选择非阻塞删除,仅将 keys 从 keyspace 元数据中删除,真正的删除会在后续异步操作。 -
expire key 10为给定的 key 设置 10 秒过期时间 -
ttl key查看还有多少秒过期,-1表示永不过期,-2表示已过期 -
select命令切换数据库 -
dbsize查看当前数据库的 key 的数量 -
flushdb清空当前库 -
flushall清空全部库
2. Redis五大数据类型
2.1 Redis字符串 (String)
简介
String 是 Redis 最基本的类型,你可以理解为与 Memcached 一模一样的类型,一个 key 对应一个 value。String 类型是二进制安全的,意味着 Redis 的 string 可以包含任何数据,比如 jpg 图片或序列化的对象。一个 Redis 中字符串 value 最多可以是 512M。
常用命令
-
set <key> <value> [参数]添加键值对NX:当数据库中 key 不存在时,可以将 key-value 添加数据库XX:当数据库中 key 存在时,可以将 key-value 添加数据库,与 NX 参数互斥EX:key 的超时秒数PX:key 的超时毫秒数,与 EX 互斥
-
get <key>查询对应键值 -
append <key> <value>将给定的<value>追加到原值的末尾 -
strlen <key>获得值的长度 -
setnx <key> <value>只有在 key 不存在时设置 key 的值 -
incr <key>将 key 中储存的数字值加 1(只能对数字值操作,如果为空则新增值为 1) -
decr <key>将 key 中储存的数字值减 1(只能对数字值操作,如果为空则新增值为 -1) -
incrby <key> <步长>/decrby <key> <步长>将 key 中储存的数字值增减自定义步长。 -
mset <key1> <value1> <key2> <value2> ...同时设置一个或多个 key-value 对 -
mget <key1> <key2> <key3> ...同时获取一个或多个 value -
msetnx <key1> <value1> <key2> <value2> ...同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在(原子性,有一个失败则都失败) -
getrange <key> <起始位置> <结束位置>获得值的范围,类似 Java 中的substring,前包后包 -
setrange <key> <起始位置> <value>用<value>覆写<key>所储存的字符串值,从<起始位置>开始(索引从 0 开始)。 -
setex <key> <过期时间> <value>设置键值的同时,设置过期时间,单位秒。 -
getset <key> <value>以新换旧,设置了新值的同时获得旧值。
1. Key 操作
keys *:查看当前数据库中所有的 key。exists <key>:检查指定 key 是否存在,存在返回1,否则返回0。del <key>:删除指定的 key。type <key>:查看指定 key 的类型。expire <key> <seconds>:为指定 key 设置过期时间(单位:秒)。ttl <key>:查看指定 key 剩余的过期时间(秒数),-1表示永不过期,-2表示已过期。
2. String 操作
set <key> <value>:为 key 设置字符串值。get <key>:获取 key 对应的字符串值。incr <key>:将 key 中储存的数字值加 1。decr <key>:将 key 中储存的数字值减 1。append <key> <value>:将给定的 value 追加到指定 key 的原值后。
3. List 操作
lpush <key> <value>:将 value 插入列表的左侧。rpush <key> <value>:将 value 插入列表的右侧。lpop <key>:移除并返回列表的左侧元素。rpop <key>:移除并返回列表的右侧元素。lrange <key> <start> <end>:获取列表指定范围内的元素。
4. Hash 操作
hset <key> <field> <value>:将 hash 表 key 中的字段 field 的值设为 value。hget <key> <field>:获取 hash 表 key 中字段 field 对应的值。hdel <key> <field>:删除 hash 表 key 中的指定字段。hgetall <key>:获取 hash 表 key 中的所有字段和值。
5. Set 操作
sadd <key> <member>:向集合 key 中添加一个元素。smembers <key>:获取集合 key 中的所有成员。srem <key> <member>:移除集合中的一个或多个成员。
6. Sorted Set 操作
zadd <key> <score> <member>:向有序集合添加成员并设置分数。zrange <key> <start> <stop>:根据分数范围获取有序集合中的成员。
7. 数据库操作
select <index>:选择 Redis 数据库,索引从 0 开始。dbsize:查看当前数据库的 key 的数量。flushdb:清空当前数据库。flushall:清空所有数据库。
8. 退出 Redis 客户端
quit:退出 Redis 客户端。
这些命令可以帮助你完成大多数常见的 Redis 操作。
RedisTemplate 操作
RedisTemplate 是 Spring Data Redis 提供的高级 Redis 操作工具,支持多种数据结构,如字符串、哈希、列表、集合和有序集合等。以下是 RedisTemplate 的常用 API 操作:
1. 基本操作(String 类型)
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 设置值
redisTemplate.opsForValue().set("key", "value");
// 获取值
Object value = redisTemplate.opsForValue().get("key");
// 设置带过期时间的值
redisTemplate.opsForValue().set("key", "value", Duration.ofSeconds(60));
// 删除键
redisTemplate.delete("key");
// 判断键是否存在
Boolean exists = redisTemplate.hasKey("key");
// 设置新值并返回旧值
Object oldValue = redisTemplate.opsForValue().getAndSet("key", "newValue");
// 自增(整数)
Long increment = redisTemplate.opsForValue().increment("counter", 1);
// 自减(整数)
Long decrement = redisTemplate.opsForValue().decrement("counter", 1);
2. 哈希操作(Hash)
// 设置哈希字段值
redisTemplate.opsForHash().put("user:1001", "name", "张三");
// 获取哈希字段值
Object name = redisTemplate.opsForHash().get("user:1001", "name");
// 获取整个哈希表
Map<Object, Object> user = redisTemplate.opsForHash().entries("user:1001");
// 获取哈希表所有字段
Set<Object> keys = redisTemplate.opsForHash().keys("user:1001");
// 获取哈希表所有值
List<Object> values = redisTemplate.opsForHash().values("user:1001");
// 删除哈希字段
redisTemplate.opsForHash().delete("user:1001", "name");
// 判断哈希字段是否存在
Boolean exists = redisTemplate.opsForHash().hasKey("user:1001", "age");
// 增加哈希字段的数值
redisTemplate.opsForHash().increment("user:1001", "age", 1);
3. 列表操作(List)
// 左进(队列模式)
redisTemplate.opsForList().leftPush("myList", "A");
// 右进(栈模式)
redisTemplate.opsForList().rightPush("myList", "B");
// 获取列表长度
Long size = redisTemplate.opsForList().size("myList");
// 获取指定索引的值
Object item = redisTemplate.opsForList().index("myList", 0);
// 获取列表范围内的所有元素
List<Object> list = redisTemplate.opsForList().range("myList", 0, -1);
// 移除左端元素
Object leftPop = redisTemplate.opsForList().leftPop("myList");
// 移除右端元素
Object rightPop = redisTemplate.opsForList().rightPop("myList");
// 删除指定数量的值
redisTemplate.opsForList().remove("myList", 2, "A");
4. 集合操作(Set)
// 添加元素到集合
redisTemplate.opsForSet().add("mySet", "A", "B", "C");
// 获取集合所有元素
Set<Object> members = redisTemplate.opsForSet().members("mySet");
// 判断元素是否存在
Boolean isMember = redisTemplate.opsForSet().isMember("mySet", "A");
// 移除元素
redisTemplate.opsForSet().remove("mySet", "B");
// 获取集合大小
Long size = redisTemplate.opsForSet().size("mySet");
// 获取两个集合的交集
Set<Object> intersection = redisTemplate.opsForSet().intersect("set1", "set2");
// 获取两个集合的并集
Set<Object> union = redisTemplate.opsForSet().union("set1", "set2");
// 获取两个集合的差集
Set<Object> difference = redisTemplate.opsForSet().difference("set1", "set2");
5. 有序集合操作(ZSet)
// 添加元素到有序集合
redisTemplate.opsForZSet().add("myZSet", "A", 10);
redisTemplate.opsForZSet().add("myZSet", "B", 20);
// 获取集合中的所有元素
Set<Object> elements = redisTemplate.opsForZSet().range("myZSet", 0, -1);
// 获取带分数的集合元素
Set<ZSetOperations.TypedTuple<Object>> tuples = redisTemplate.opsForZSet().rangeWithScores("myZSet", 0, -1);
// 获取元素的排名
Long rank = redisTemplate.opsForZSet().rank("myZSet", "A");
// 增加元素的分数
redisTemplate.opsForZSet().incrementScore("myZSet", "A", 5);
// 删除元素
redisTemplate.opsForZSet().remove("myZSet", "B");
// 获取指定分数范围内的元素
Set<Object> rangeByScore = redisTemplate.opsForZSet().rangeByScore("myZSet", 10, 30);
6. 其他操作
// 设置键的过期时间
redisTemplate.expire("key", Duration.ofMinutes(5));
// 获取剩余存活时间(秒)
Long ttl = redisTemplate.getExpire("key");
// 清空所有 Redis 数据
redisTemplate.getConnectionFactory().getConnection().flushDb();
这些 RedisTemplate API 覆盖了 Redis 的主要数据结构操作,实际开发中可根据业务需求进行封装和优化。
当然可以 ✅ 下面是一篇完整的、结构清晰的博客文章,适合放在团队知识库、个人博客或掘金等平台上。 主题围绕「Redis 存取 Java 对象的正确与高效方式」,并结合你代码中出现的场景。
💡RedisTemplate 中存取 Java 对象的正确姿势(含 List 示例)
在 Java 开发中,我们经常会临时把一些对象、列表或缓存数据存入 Redis。 例如下面的场景:
// 临时放入 Redis
String cacheKey = StrUtil.format(FILE_UPLOAD_ERROR_KEY, id);
redisTemplate.opsForValue().set(cacheKey, cachedDataList);
但问题来了—— 当我们从 Redis 取出数据时,如何正确还原成原始对象类型? 本文将带你彻底搞清楚几种常见的序列化方式与推荐实践。
🧱 一、默认情况:JDK 序列化
Spring Boot 中的 RedisTemplate 默认使用:
JdkSerializationRedisSerializer
也就是说,它会把对象序列化成二进制字节数组,Redis 中看到的内容是乱码。
✅ 存入:
redisTemplate.opsForValue().set(cacheKey, cachedDataList);
✅ 取出:
@SuppressWarnings("unchecked")
List<ReconciliationDetailUpload> cachedList =
(List<ReconciliationDetailUpload>) redisTemplate.opsForValue().get(cacheKey);
⚠️ 注意:
ReconciliationDetailUpload必须实现Serializable接口- 序列化和反序列化的 RedisTemplate 必须一致
- Redis 中无法直接查看可读内容
这种方式虽然简单,但可读性差,跨语言不兼容,不太推荐用于业务数据缓存。
📘 二、推荐方式:JSON 序列化(Jackson)
更常见的方式是使用 JSON 存储对象。
在 Spring Boot 中可以通过配置 GenericJackson2JsonRedisSerializer:
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
✅ 存入:
redisTemplate.opsForValue().set(cacheKey, cachedDataList);
✅ 取出:
List<ReconciliationDetailUpload> cachedList =
(List<ReconciliationDetailUpload>) redisTemplate.opsForValue().get(cacheKey);
这样 Redis 中看到的是清晰的 JSON 格式,可直接查看。 Jackson 会自动保存类型信息(
@class字段),方便反序列化。
🧩 三、如果使用的是 StringRedisTemplate
有些项目只配置了 StringRedisTemplate,它只能操作字符串。
这时就需要手动将对象序列化为 JSON:
✅ 存入:
stringRedisTemplate.opsForValue().set(cacheKey, JSONUtil.toJsonStr(cachedDataList));
✅ 取出:
String json = stringRedisTemplate.opsForValue().get(cacheKey);
List<ReconciliationDetailUpload> cachedList =
JSONUtil.toList(json, ReconciliationDetailUpload.class);
这里推荐使用 Hutool 的 JSONUtil,API 简洁、类型安全。
⚙️ 四、三种方式对比
| 序列化方式 | 可读性 | 性能 | 是否推荐 | 说明 |
|---|---|---|---|---|
| JDK 序列化 | ❌ 无 | ✅ 中等 | ⚠️ 一般 | 默认方式,二进制 |
| Jackson JSON | ✅ 高 | ✅ 中等 | ✅ 推荐 | 可读、跨语言兼容 |
| Hutool JSON + StringRedisTemplate | ✅ 高 | ✅ 快 | ✅ 推荐 | 简洁灵活 |
💡 五、实际项目推荐方案
结合性能、可读性、兼容性综合考虑,推荐使用:
// 写入
redisTemplate.opsForValue().set(cacheKey, JSONUtil.toJsonStr(cachedDataList));
// 读取
String json = (String) redisTemplate.opsForValue().get(cacheKey);
List<ReconciliationDetailUpload> cachedList =
JSONUtil.toList(json, ReconciliationDetailUpload.class);
优点:
- Redis 中可直接查看 JSON 内容;
- 不依赖类型信息;
- 与前端或其他语言兼容;
- 一行即可反序列化。
🔍 六、常见问题汇总
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 取出来是乱码 | 使用了 JDK 序列化 | 改为 JSON 序列化 |
| 反序列化报错 | 对象结构变动或无序列化器 | 使用 Jackson 或 Hutool JSON |
| 数据为空 | Redis key 拼写不一致 | 打印日志检查 key |
| JSON 转对象失败 | 泛型类型不明确 | 指定 List<T> 类型解析 |
✅ 七、总结
“Redis 存储对象的关键不在 Redis,而在于序列化。”
常见三种方式:
| 场景 | 推荐方式 |
|---|---|
| 临时缓存 | Hutool JSON |
| 系统内部结构体 | Jackson JSON |
| 需要高性能序列化 | Fastjson2 / Kryo(可选) |
一句话总结:
⚙️ 存之前想清楚怎么“还原”, 📦 选对序列化工具,Redis 就能存一切!