SpringDataRedis存储Redis的数据序列化

在使用Spring Data Redis存储数据至Redis时,选择合适的序列化策略至关重要。它不仅影响数据存储的效率和空间利用率,还关系到跨语言兼容性和系统的扩展性。适当的序列化方式可以确保数据正确无误地被存储和读取,提升系统的稳定性和维护性,避免由于默认序列化带来的乱码或不兼容问题,从而保障应用的高效运行和数据的安全完整。

目录

序列化介绍

问题解析

问题测试

解决方案

方案一

方案二


序列化介绍

序列化 是指将对象的状态信息转换为可以存储或传输的形式的过程。在反序列化时,这个过程是相反的,即将这些信息还原成对象。

当你将数据存储到Redis中时,如果发现数据变成字节,这通常与序列化方式有关。指在Java环境中使用Redis客户端,默认情况下会使用JDK内置的序列化方式(即**Serializable** 接口及**ObjectOutputStream**等类来实现对象的序列化)。

问题解析

兼容性问题:JDK序列化格式是Java特有的,这意味着只有Java程序才能反序列化这些对象。如果你的系统中有非Java组件需要访问Redis中的数据,那么它们将无法直接读取这些序列化的对象。

性能问题:JDK序列化机制有时会比较慢,并且生成的序列化内容可能比其他序列化方法(如JSON, Protobuf, Avro等)更大,从而影响网络传输效率和存储空间。

安全性考虑:反序列化不受信任的数据源可能导致安全漏洞,例如反序列化攻击。这是因为反序列化过程会执行某些代码,如果攻击者能够控制输入流,就可能利用这一点执行恶意代码.

其实可读性也非常差(这谁能看出来name=小明, age=18是上面这一大串)

问题测试

使用SpringDataRedis客户端:

创建一个测试的SpringBoot项目,引入依赖:

java 复制代码
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

在application.yaml加入:

java 复制代码
spring:
  data:
    redis:
      host: localhost
      port: 6379
      password:
      lettuce:
        pool:
          max-active: 8
          min-idle: 0
          max-idle: 8
          max-wait: 1000

在测试类,加入以下代码:

复制代码
@SpringBootTest
class SpringDataRedisDemoApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void testString() {
        redisTemplate.opsForValue().set("time","12");
        Object time = redisTemplate.opsForValue().get("time");
        System.out.println("time = " + time);
    }


    @Test
    void testUser() {
        redisTemplate.opsForValue().set("user",new User("小明",18));
        User user = (User) redisTemplate.opsForValue().get("user");
        System.out.println("user = " + user);
    }
}

运行后查看Java客户端工具:

解决方案

方案一

配置**RedisTemplate,**使用JSON作为序列化格式,实现自动序列化和反序列化。

加入下列代码,设置特定的序列化工具(GenericJackson2JsonRedisSerializer

java 复制代码
@Configuration
public class RedisConfig {
    /**
     * RedisTemplate配置序列化规则
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(connectionFactory);
        // 创建Json序列化工具
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置key的序列化规则
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // 设置value的序列化规则
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }
}

修改测试类注入的RedisTemplate类型

java 复制代码
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

运行结果如下:

可以看到可读性大大提高,可以确保所有存储到Redis中的数据都以一种一致且易于理解的方式进行序列化和反序列化,提升了与Redis交互时的序列化效率、数据兼容性和易用性,使得存储和检索过程更加高效和直观。

方案二

方案一有一个缺点,在储存对象时,把类的class类型写入了JSON结果中,存入Redis,带来了额外的内存开销。(在大量数据的情况下可能给内存带来压力)

使用StringRedisTemplate,手动实现序列化和反序列化。

java 复制代码
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    private static final ObjectMapper mapper = new ObjectMapper();
    
    @Test
    void testUser() throws JsonProcessingException {
        //创建对象
        User user = new User("张三", 18);
        // 手动序列化
        String json = mapper.writeValueAsString(user);
        // 存入redis
        stringRedisTemplate.opsForValue().set("users",json);
        // 取出数据
        String users = stringRedisTemplate.opsForValue().get("users");
        // 手动反序列化
        User user1 = mapper.readValue(users, User.class);
        // 输出
        System.out.println("user1 = " + user1);
    }

实现效果如下:

实现了去除类的class类型,节省了内存。

相关推荐
CL_IN1 小时前
高效集成销售订单数据到MySQL的方法
android·数据库·mysql
架构文摘JGWZ1 小时前
SQLite?低调不是小众...
数据库·后端·学习·sqlite
Master_清欢1 小时前
vue3实现跨页面缓存
缓存·vue
划水哥~2 小时前
SQL99 多表查询
数据库·sql
王ASC2 小时前
kettle的转换中sql不按设计顺序执行原因分析与解决办法
数据库·sql
Elastic 中国社区官方博客2 小时前
Elasticsearch:语义文本 - 更简单、更好、更精炼、更强大 8.18
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
老大白菜2 小时前
DeepSeek API 客户端使用文档
数据库
元气满满的热码式3 小时前
MySQL启动报错解决
运维·数据库·mysql
XMYX-03 小时前
解决 Redis 后台持久化失败的问题:内存不足导致 fork 失败
java·数据库·redis
猿小喵3 小时前
MySQL异常SQL排查
数据库·sql·mysql