news 2026/4/15 10:29:37

Spring Data Redis

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Data Redis

1. Spring Data Redis 简介

Spring Data Redis 是 Spring Data 家族的一部分,它为 Spring 应用提供了对 Redis 存储的高级抽象。它屏蔽了底层连接库(如 Jedis 或 Lettuce)的复杂实现细节,使开发者能够通过统一的 API 与 Redis 进行交互。

核心价值

  • 连接管理:自动管理 Redis 连接的生命周期及连接池。
  • 操作封装:将 Redis 原始命令封装为面向对象的 API。
  • 异常转化:将底层的 Redis 异常转换为 Spring 统一的DataAccessException体系。

2. RedisTemplate 介绍

RedisTemplate是 Spring Data Redis 的核心类,它提供了执行 Redis 操作的模板方法。

数据结构操作映射

RedisTemplate将 Redis 的基本数据结构划分为不同的操作接口:

接口方法对应的 Redis 数据结构
opsForValue()String(字符串)
opsForHash()Hash(哈希)
opsForList()List(列表)
opsForSet()Set(集合)
opsForZSet()ZSet(有序集合)

3. Spring Boot 集成步骤

Spring Boot 3.4.2环境下,集成步骤如下:

3.1 引入依赖 (pom.xml)

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>

3.2 配置连接信息 (application.yaml)

spring:data:redis:host:127.0.0.1port:6379database:0jedis:pool:max-active:8# 最大连接数max-idle:8# 最大空闲连接

4. RedisTemplate 常见操作示例

4.1 String 字符串操作

@AutowiredprivateRedisTemplate<String,Object>redisTemplate;publicvoidtestString(){// 写入数据redisTemplate.opsForValue().set("user:name","czl");// 读取数据Stringvalue=(String)redisTemplate.opsForValue().get("user:name");// 带过期时间的写入redisTemplate.opsForValue().set("code","1234",Duration.ofMinutes(5));}

4.2 Hash 哈希操作

publicvoidtestHash(){Stringkey="user:info:1";// 存入单个字段redisTemplate.opsForHash().put(key,"name","tiger");// 获取单个字段Objectname=redisTemplate.opsForHash().get(key,"name");// 获取全部字段Map<Object,Object>entries=redisTemplate.opsForHash().entries(key);}

4.3 List 列表操作

publicvoidtestList(){Stringkey="queue:task";// 从左侧推入redisTemplate.opsForList().leftPush(key,"task1");// 从右侧弹出Objecttask=redisTemplate.opsForList().rightPop(key);}

4.4 Set 集合操作

publicvoidtestSet(){Stringkey="tags";// 添加元素redisTemplate.opsForSet().add(key,"java","redis","spring");// 判断是否存在BooleanisMember=redisTemplate.opsForSet().isMember(key,"java");}

5. RedisTemplate 与 Jedis 实例关系

在 Spring Boot 应用中,RedisTemplate与底层Jedis实例之间并非一比一的绑定关系,而是一种典型的“多对一”或“一对多”的解耦模型

5.1 实例数量对比

一对多关系

  • RedisTemplate
    在一个 Spring Context 中,你通常只需要配置一个RedisTemplate<String, Object>就能在全工程中通过@Autowired共享。它是无状态的,专门负责定义操作逻辑和序列化规则。不过也可以配置多个定制化RedisTemplate,关键是与Jedis实例是一对多关系。
  • Jedis 实例:是一个连接池
    底层通过JedisPool维护了多个长连接实例。具体数量由你在application.yaml中配置的max-active决定。

5.2 动态映射关系

当你调用redisTemplate.opsForValue().set(...)时,发生的数量调度如下:

  1. 借用阶段RedisTemplate拦截到请求,从底层的JedisPool中申请一个当前的空闲Jedis实例。
  2. 独占阶段:在命令执行期间,这个特定的Jedis实例被该线程独占,其他线程无法使用它。
  3. 归还阶段:操作完成后,RedisTemplate自动释放连接,将该Jedis实例归还给池中。

5.3 结论

  • 逻辑层:你只需要维护1 个RedisTemplate即可处理所有的并发请求。
  • 物理层:底层的JedisPool会根据并发量动态分配N 个Jedis实例来支持这 1 个模板的工作。

6. RedisTemplate 序列化器深度解析

6.1 为什么要使用序列化器?

Redis 数据库本身是二进制安全的,它只能存储字节序列(byte array)。而 Java 是面向对象的语言,我们操作的是StringInteger或自定义的UserDO对象。

序列化器(Serializer)的作用:就是充当 Java 对象与 Redis 字节流之间的“翻译官”。

  • 存入时:将 Java 对象转换成二进制字节。
  • 读取时:将二进制字节转换回 Java 对象。
示例:不配置序列化器的后果

假设你使用 Spring 默认的RedisTemplate(未手动配置序列化器),执行以下操作:

redisTemplate.opsForValue().set("name","虎哥");

虽然代码运行成功,但当你通过命令行或 Redis Insight 查看时,你会发现:

  • Key变成了:\xac\xed\x00\x05t\x00\x04name
  • Value变成了:\xac\xed\x00\x05t\x00\x06\xe8\x99\x8e\xe5\x93\xa5

这是因为默认使用了JdkSerializationRedisSerializer,它在数据前添加了 Java 序列化协议的魔数(\xac\xed)和类元数据。这导致数据在 Redis 中不可读,且其他语言(如 Python、Go)无法解析。

6.2 序列化器的具体用法

在 Spring Boot 3.4.2 环境下,我们通过自定义RedisConfig类来指定序列化规则。

1. 配置代码示例

通常建议Key 使用 String 序列化Value 使用 JSON 序列化,以达到最佳的可读性和兼容性。

@ConfigurationpublicclassRedisConfig{@BeanpublicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactoryfactory){RedisTemplate<String,Object>template=newRedisTemplate<>();template.setConnectionFactory(factory);// 1. 指定 Key 的序列化器:StringRedisSerializer// 效果:存入 "name",Redis 中显示为字符串 "name"template.setKeySerializer(newStringRedisSerializer());template.setHashKeySerializer(newStringRedisSerializer());// 2. 指定 Value 的序列化器:GenericJackson2JsonRedisSerializer// 效果:存入对象,Redis 中显示为标准 JSON 字符串template.setValueSerializer(newGenericJackson2JsonRedisSerializer());template.setHashValueSerializer(newGenericJackson2JsonRedisSerializer());returntemplate;}}
2. 配置后的存储效果对比

在使用上述配置后,同样的set("name", "虎哥")操作,Redis 中的表现如下:

存储部分默认 Jdk 序列化(乱码)配置后(明文/JSON)
Key\xac\xed\x00\x05t\x00\x04namename
Value\xac\xed\x00\x05t\x00..."虎哥"
对象 Value二进制乱码{"id":1, "nickname":"虎哥"}

7. Jackson 序列化器的内存占用问题及优化方案

7.1 Jackson 序列化器的“多余”字节码问题

在使用GenericJackson2JsonRedisSerializer时,为了实现自动反序列化,Jackson 会在生成的 JSON 字符串中额外添加一个名为@class的字段。

示例:自动序列化的存储结果

假设存储一个简单的UserDO对象:

{"@class":"cn.iocoder.boot.springdataredis.UserDO","id":1,"nickname":"虎哥"}
  • 问题所在:这个@class字段包含了类全路径名,在大型项目中,这个字符串往往比业务数据本身还要长。
  • 内存影响:如果你有数百万个 Key,这些重复的类路径字符串会额外占用大量的 Redis 内存空间,增加硬件成本和网络带宽压力。

7.2 解决方案:手动序列化(String + ObjectMapper)

为了追求极致的内存利用率,业界常用的方案是:全局只使用StringRedisTemplate(或 String 序列化器),在代码逻辑中手动利用ObjectMapper(或JsonUtils)进行对象转换

1. 核心思路
  • 存储时:调用JsonUtils.toJsonString(obj)得到纯净的 JSON,不带@class标记,存入 Redis。
  • 读取时:取出 String,根据业务需要调用JsonUtils.parseObject(json, UserDO.class)还原对象。
2. 代码实现示例

基于你已有的Spring Boot 3.4.2环境 和JsonUtils

@ServicepublicclassUserService{@AutowiredprivateStringRedisTemplatestringRedisTemplate;// 默认已有的 String 模板publicvoidsaveUserManual(UserDOuser){// 1. 手动序列化为纯净 JSON 字符串StringjsonStr=JsonUtils.toJsonString(user);// 2. 存入 RedisstringRedisTemplate.opsForValue().set("user:"+user.getId(),jsonStr);}publicUserDOgetUserManual(Longid){// 3. 获取纯净 JSON 字符串StringjsonStr=stringRedisTemplate.opsForValue().get("user:"+id);// 4. 手动反序列化,通过 Class 参数明确目标类型returnJsonUtils.parseObject(jsonStr,UserDO.class);}}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/8 15:54:37

2026 年人才战略新趋势:智慧人力系统的数据洞察与预测分析应用

在企业竞争日益聚焦于人才的当下&#xff0c;人才战略的科学性直接影响企业的长远发展。然而&#xff0c;传统人力管理中依赖经验判断的模式&#xff0c;往往导致人才布局与业务需求脱节。智慧人力系统的出现&#xff0c;通过数据洞察与预测分析&#xff0c;为企业人才战略提供…

作者头像 李华
网站建设 2026/4/1 20:29:46

OpenCode+Oh-my-opencode插件(国内友好,免费模型)——筑梦之路

https://blog.csdn.net/qq_34777982/article/details/157651712?spm1011.2124.3001.6209 之前使用ClaudeCode调用本地模型&#xff0c;效果不是太好&#xff0c;试用了下opencode效果还行&#xff0c;比较推荐&#xff0c;这里记录下环境搭建过程。 前置条件 nodejs 22.10…

作者头像 李华
网站建设 2026/4/11 18:55:47

智能设备锁屏密码忘记?手表、电视等官方解决方案

除了手机、平板、电脑&#xff0c;智能手表、智能电视、智能音箱等设备也常设置锁屏/登录密码&#xff0c;忘记后同样无需慌张&#xff0c;各大品牌均有官方解锁方法&#xff0c;操作简单&#xff0c;无需第三方工具&#xff0c;兼顾设备安全和使用便捷。注意&#xff1a;智能设…

作者头像 李华
网站建设 2026/4/8 19:16:01

HTML DOM 访问

HTML DOM 访问 引言 HTML DOM(文档对象模型)是现代Web开发的基础。它允许开发者通过JavaScript与HTML文档进行交互,从而实现丰富的网页功能。本文将深入探讨HTML DOM的访问方法,帮助开发者更好地理解和运用DOM。 什么是HTML DOM HTML DOM是一种将HTML文档表示为树形结构…

作者头像 李华
网站建设 2026/4/8 19:12:02

2026健身器材出海新思路:海外红人营销如何提前完成心智占位

健身器材的购买&#xff0c;很少始于“我现在要买一台器械”。更多时候&#xff0c;它来自更早期、也更模糊的心理触发点——对健康状态的隐性焦虑、对身材变化的自我察觉、对居家空间功能性的重新审视。这些触发并不直接指向某个产品&#xff0c;而是以情绪、状态或生活场景的…

作者头像 李华