【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(上)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑(上)

前言


上一篇已经介绍了优雅的操作Redis:

【小家Spring】Spring Boot中使用RedisTemplate优雅的操作Redis,并且解决RedisTemplate泛型注入的问题。本篇着重介绍一下几种常用的序列化方式


最近在做一个项目,由于并发量大,大量使用到了RedisTemplate来操作Redis。但使用过程中,遇到了不少的坑,各种翻看源码来跟踪,也总结出了不少的经验。


因此今天专门做一篇专文来记录这些坑,也具体说说RedisTemplate的各种序列化方式的差异性。希望对大家也能有所帮助,帮助大家解决一些疑惑


1.序列化问题


    RedisTemplate在遇到复杂类型的返序列化时,即使加了泛型,获取到的时机类型为LinedHashMap,需要得到结果后再次返序列化,不然会报类型转换异常。

如下:这样处理才是安全的:

image.png


在执行序列化的时候,操作的如果是Bean,必须有默认构造器,否则报错


2.redis集群问题(关于集群的这几个问题,后续在专门演示和解释)


如果连接的为Redis集群,则不能用管道的方法,除非改写管道的类


模糊查询的时候需要获取到所有的node信息,依次查询


Spring提供的序列化方式


从源码里看:


image.png


我们可以很清晰的看到,Spring为我们提供了6种不同的序列化方式。


特别说明一下:如果你是在Spring Boot1.5.x环境下使用,你可能看到是9种实现或者是7种实现,如下图所示


image.png


解释:


关于前面两个,并非Spring官方提供,而是由alibaba的FastJson自己实现的。我们看看FastJson的包结构,发现它很友好的提供了一些常用的转化器


image.png


因此此处暂时不做过多描述,后面再说。


另外还有一个JacksonJsonRedisSerializer类,被标记为过期。而这个类在SpringBoot2.0就直接被移除掉了,因此以后的版本不用理会了。


下面主要介绍一下,Spring官方现在还存在的6大序列化器:


Generic单词意思:一般的; 通用的;类的,属性的;


1.OxmSerializer

以xml格式存储(但还是String类型~),解析起来也比较复杂,效率也比较低。因此几乎没有人再使用此方式了


2.JdkSerializationRedisSerializer

从源码里可以看出,这是RestTemplate类默认的序列化方式。若你没有自定义,那就是它了。


  @Override
  public void afterPropertiesSet() {
    super.afterPropertiesSet();
    boolean defaultUsed = false;
    if (defaultSerializer == null) {
      defaultSerializer = new JdkSerializationRedisSerializer(
          classLoader != null ? classLoader : this.getClass().getClassLoader());
    }
    ...


使用JDK自带的序列化方式,有明显的缺点:

首先它要求存储的对象都必须实现java.io.Serializable接口,比较笨重

其次,他存储的为二进制数据,这对开发者是不友好的

再次,因为他存储的为二进制。但是有时候,我们的Redis会在一个项目的多个project中共用,这样如果同一个可以缓存的对象在不同的project中要使用两个不同的key来分别缓存,既麻烦,又浪费。


使用JDK提供的序列化功能。 优点是反序列化时不需要提供(传入)类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。

    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void contextLoads() {
        ValueOperations<String, Person> valueOperations = redisTemplate.opsForValue();
        valueOperations.set("aaa", new Person("fsx", 24));
        Person p = valueOperations.get("aaa"); //Person(name=fsx, age=24)
        System.out.println(p);
    }


存储的为二进制,根本开不出来是什么,对开发者调试也很不友好



image.png


    3.StringRedisSerializer

也是StringRedisTemplate默认的序列化方式,key和value都会采用此方式进行序列化,是被推荐使用的,对开发者友好,轻量级,效率也比较高。

(例子略)


    4.GenericToStringSerializer

他需要调用者给传一个对象到字符串互转的Converter(相当于转换为字符串的操作交给转换器去做),个人觉得使用起来其比较麻烦,还不如直接用字符串呢。所以不太推荐使用


后面两种序列化方式是重点


    5.Jackson2JsonRedisSerializer

从名字可以看出来,这是把一个对象以Json的形式存储,效率高且对调用者友好


优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。

但缺点也非常致命:那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其在反序列化过程中用到了类型信息(必须根据此类型信息完成反序列化)。


   6.GenericJackson2JsonRedisSerializer

基本和上面的Jackson2JsonRedisSerializer功能差不多,使用方式也差不多,**但是是推荐使用的**

需要注意:(使用区别)


    @Test
    public void contextLoads() {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        //ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        //此处泛型 因为编译器无法校验  所以如果value序列化方式是字符串 下面就会报错了
        ValueOperations<String, Person> valueOperations = redisTemplate.opsForValue();
        valueOperations.set("key", new Person("fsx", 24)); //java.lang.ClassCastException: com.fsx.run2.bean.Person cannot be cast to java.lang.String
        Person value = valueOperations.get("key");
        System.out.println(value);
    }


如上,假如我value的序列化方式设置为String序列化器。但是set值的时候放对象了。这个时候就直接报错了,并不会自动调用toString()方法,此处一定要注意。还需要特别是初始化RestTemplate的时候,value的序列化方式禁止使用有类型偏向的StringRedisSerializer。若有需要,你直接使用StringRedisTemplate操作即可

相关文章
|
13天前
|
存储 NoSQL Java
配置RedisTemplate序列化机制
通过上述步骤,你可以灵活配置RedisTemplate的序列化机制,根据应用需求选择合适的序列化器,从而确保数据在Redis中的存储和读取效率最优化。配置合适的序列化机制对于性能和存储效率至关重要,而且这样可以确保数据在存储和传输过程中的结构清晰和一致性。
95 11
|
28天前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
2月前
|
存储 NoSQL Java
RedisTemplate序列化问题排查与优化建议。
最后,对于序列化问题的深入排查与优化,建议编写具有代表性的单元测试,以验证RedisTemplate配置的正确性和效能。此外,可以在非生产环境中测试不同的序列化策略,找到最适合当前应用场景的序列化方式。通过不断迭代和优化,达到持续提高数据存取能力的目标。
126 13
|
6月前
|
NoSQL 安全 Java
深入理解 RedisConnectionFactory:Spring Data Redis 的核心组件
在 Spring Data Redis 中,`RedisConnectionFactory` 是核心组件,负责创建和管理与 Redis 的连接。它支持单机、集群及哨兵等多种模式,为上层组件(如 `RedisTemplate`)提供连接抽象。Spring 提供了 Lettuce 和 Jedis 两种主要实现,其中 Lettuce 因其线程安全和高性能特性被广泛推荐。通过手动配置或 Spring Boot 自动化配置,开发者可轻松集成 Redis,提升应用性能与扩展性。本文深入解析其作用、实现方式及常见问题解决方法,助你高效使用 Redis。
591 4
|
7月前
|
NoSQL Java 关系型数据库
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
本文介绍在 Spring Boot 中集成 Redis 的方法。Redis 是一种支持多种数据结构的非关系型数据库(NoSQL),具备高并发、高性能和灵活扩展的特点,适用于缓存、实时数据分析等场景。其数据以键值对形式存储,支持字符串、哈希、列表、集合等类型。通过将 Redis 与 Mysql 集群结合使用,可实现数据同步,提升系统稳定性。例如,在网站架构中优先从 Redis 获取数据,故障时回退至 Mysql,确保服务不中断。
282 0
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 介绍
|
3月前
|
NoSQL Java Redis
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
406 2
|
5月前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
197 32
|
7月前
|
NoSQL Java API
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Spring Boot 集成 Redis
本文介绍了在Spring Boot中集成Redis的方法,包括依赖导入、Redis配置及常用API的使用。通过导入`spring-boot-starter-data-redis`依赖和配置`application.yml`文件,可轻松实现Redis集成。文中详细讲解了StringRedisTemplate的使用,适用于字符串操作,并结合FastJSON将实体类转换为JSON存储。还展示了Redis的string、hash和list类型的操作示例。最后总结了Redis在缓存和高并发场景中的应用价值,并提供课程源代码下载链接。
1687 0
|
7月前
|
NoSQL Java Redis
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Redis 安装
本教程介绍在 VMware 虚拟机(CentOS 7)或阿里云服务器中安装 Redis 的过程,包括安装 gcc 编译环境、下载 Redis(官网或 wget)、解压安装、修改配置文件(如 bind、daemonize、requirepass 等设置)、启动 Redis 服务及测试客户端连接。通过 set 和 get 命令验证安装是否成功。适用于初学者快速上手 Redis 部署。
161 0
|
10月前
|
存储 NoSQL Java
使用lock4j-redis-template-spring-boot-starter实现redis分布式锁
通过使用 `lock4j-redis-template-spring-boot-starter`,我们可以轻松实现 Redis 分布式锁,从而解决分布式系统中多个实例并发访问共享资源的问题。合理配置和使用分布式锁,可以有效提高系统的稳定性和数据的一致性。希望本文对你在实际项目中使用 Redis 分布式锁有所帮助。
582 5