针对不同使用场景,Redis的Value应该如何序列化,优缺点如何,进来看

在 Spring Boot 环境中,Redis 的 Value 序列化方式选择对系统性能、可维护性和兼容性有重要影响。下面我将介绍几种常见的序列化方案及其使用场景。

方案一:Jackson2JsonRedisSerializer(JSON 序列化)

适用场景

  • 需要人类可读的数据格式
  • 需要与其他语言或系统交互
  • 数据结构复杂且经常变化

优缺点

优点:

  • 可读性好
  • 跨语言兼容性强
  • 支持复杂对象结构

缺点:

  • 序列化/反序列化性能一般
  • 存储空间占用相对较大

使用示例

arduino 复制代码
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // 使用 Jackson2JsonRedisSerializer 序列化 value
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), 
                ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        
        return template;
    }
}

方案二:GenericJackson2JsonRedisSerializer(通用 JSON 序列化)

适用场景

  • 需要存储多种类型对象
  • 需要类型信息保留在 JSON 中
  • 需要更好的兼容性

优缺点

优点:

  • 自动添加类型信息
  • 支持多态类型
  • 兼容性好

缺点:

  • JSON 中包含类型信息,体积稍大
  • 性能略低于普通 Jackson 序列化

使用示例

arduino 复制代码
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // 使用 GenericJackson2JsonRedisSerializer 序列化 value
        GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
        
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        
        return template;
    }
}

方案三:JdkSerializationRedisSerializer(JDK 序列化)

适用场景

  • 单一 Java 环境使用
  • 对可读性要求不高
  • 需要序列化复杂对象

优缺点

优点:

  • 支持所有可序列化 Java 对象
  • 实现简单

缺点:

  • 数据不可读
  • 跨语言兼容性差
  • 序列化后数据体积较大

使用示例

arduino 复制代码
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // 使用 JdkSerializationRedisSerializer 序列化 value
        JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer();
        
        template.setValueSerializer(serializer);
        template.setHashValueSerializer(serializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        
        return template;
    }
}

方案四:StringRedisSerializer(字符串序列化)

适用场景

  • 存储简单字符串或已序列化的数据
  • 需要手动控制序列化过程
  • 性能要求极高的场景

优缺点

优点:

  • 性能最好
  • 存储空间最小

缺点:

  • 需要手动处理对象序列化
  • 不支持复杂对象直接存储

使用示例

arduino 复制代码
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // 所有值都作为字符串处理
        template.setValueSerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new StringRedisSerializer());
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        
        return template;
    }
}

// 使用时需要手动序列化对象
@Component
public class UserService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    public void saveUser(User user) throws JsonProcessingException {
        String userJson = objectMapper.writeValueAsString(user);
        redisTemplate.opsForValue().set("user:" + user.getId(), userJson);
    }
    
    public User getUser(String id) throws JsonProcessingException {
        String userJson = redisTemplate.opsForValue().get("user:" + id);
        return objectMapper.readValue(userJson, User.class);
    }
}

总结与建议

  1. 通用场景 :推荐使用 GenericJackson2JsonRedisSerializer,它在类型安全性和可读性之间取得了良好平衡。

  2. 性能敏感场景 :如果主要是存储字符串或已序列化的数据,使用 StringRedisSerializer 并结合手动序列化可以获得最佳性能。

  3. 纯Java环境 :如果不需要与其他语言交互,可以使用 JdkSerializationRedisSerializer,但要注意它可能导致较大的存储空间占用。

  4. 高性能要求:对于极端性能要求,考虑使用 Protobuf、Kryo 或 MessagePack 等二进制序列化方案。

  5. 最佳实践

    • Key 始终使用 StringRedisSerializer
    • 根据实际需求选择合适的 Value 序列化器
    • 考虑数据迁移成本,选择稳定的序列化方案
    • 在分布式环境中,注意序列化兼容性问题

6.我的选择

arduino 复制代码
// 综合建议配置
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        
        // 使用 GenericJackson2JsonRedisSerializer 作为默认序列化器
        GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();
        
        template.setDefaultSerializer(serializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        
        return template;
    }
}

根据实际项目需求,可以选择最适合的序列化方案,也可以在系统中同时使用多种序列化方式处理不同类型的数据。

相关推荐
考虑考虑20 小时前
Jpa使用union all
java·spring boot·后端
阿杆1 天前
同事嫌参数校验太丑,我直接掏出了更优雅的 SpEL Validator
java·spring boot·后端
AAA修煤气灶刘哥2 天前
别让Redis「歪脖子」!一次搞定数据倾斜与请求倾斜的捉妖记
redis·分布式·后端
昵称为空C2 天前
SpringBoot3 http接口调用新方式RestClient + @HttpExchange像使用Feign一样调用
spring boot·后端
christine-rr2 天前
linux常用命令(4)——压缩命令
linux·服务器·redis
麦兜*2 天前
MongoDB Atlas 云数据库实战:从零搭建全球多节点集群
java·数据库·spring boot·mongodb·spring·spring cloud
麦兜*2 天前
MongoDB 在物联网(IoT)中的应用:海量时序数据处理方案
java·数据库·spring boot·物联网·mongodb·spring
汤姆yu2 天前
基于springboot的毕业旅游一站式定制系统
spring boot·后端·旅游
计算机毕业设计木哥2 天前
计算机毕设选题推荐:基于Java+SpringBoot物品租赁管理系统【源码+文档+调试】
java·vue.js·spring boot·mysql·spark·毕业设计·课程设计
凯子坚持 c2 天前
精通 Redis list:使用 redis-plus-plus 的现代 C++ 实践深度解析
c++·redis·list