【Redis优化】SpringDataRedis序列化方式对比

1 篇文章 0 订阅

一、默认序列化器

序列化器:RedisTemplate的默认序列化器JdkSerializationRedisSerializer

可以通过查看RedisTemplate源码查证

默认序列化器

数据转换:该序列化器会将数据序列化成对象,在redis中是以二进制的方式进行存储的。

注意:要保存的数据对象必须要实现Serializable,否则会提示没有序列化。

优点: 可以保存任意Java对象,并且序列化后的数据体积相对较小。

缺点: 由于以二进制方式存储,所以数据的可读性非常差。且序列化和反序列化过程相对较慢。

假设我们要存储一组数据,key为"name",value为"橘生淮南",在Java中代码如下:

redisTemplate.opsForValue().set("name","橘生淮南");
/*
*  //这里的redisTemplate在类中已经进行自动装配
*   @Autowired
*   private RedisTemplate redisTemplate;
*/

运行后我们查看存入数据库的内容

默认序列化器存入示例

可见,默认序列化器对key和value都使用了二进制进行存储,可读性非常差。因此,想要有较好的可读性,就必须更改它的序列化方式。

另外,RedisTemplate选用JdkSerializationRedisSerializer作为默认序列化器,并不是因为它是最优秀的序列化器,而是它具有一定的通用性和兼容性,可以适应大部分场景的需求。优缺点上面已经提到了,不再赘述。

二、可选序列化器

同样,通过查阅源码,可以得到支持的所有序列化器,如下:

image-20240302155945631

这里只讨论比较常用的两个序列化器:

①GenericJackson2JsonRedisSerializer: 将数据序列化成json

我们可以通过配置RedisTemplate对序列化器进行配置:

@Configuration
@Slf4j
public class RedisConfiguration {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        log.info("开始创建redis模板对象...");
        //创建Template
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate();
        //设置redis的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        /*
         注:当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,
          但是默认的key序列化器和value序列化器都是JdkSerializationRedisSerializer,
          默认序列化器导致存到Redis中的数据和原始数据有差别(可读性差),
          故设置为需要修改序列化器。
          这里使用StringRedisSerializer作为key的序列化器,转为String存储。
          使用GenericJackson2JsonRedisSerializer作为value的序列化器,转为json对象存储。
         */

        //设置redis key的序列化器
        redisTemplate.setKeySerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
        //设置redis value的序列化器
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        log.info("redis模板对象创建完成...");
        return redisTemplate;
    }
}

这里对key和value都使用了GenericJackson2JsonRedisSerializer进行序列化。

1.写入文本数据

同样运行默认序列化器中给出的代码写入数据。

image-20240302161048145

可以发现,key和value的可读性得到了保证,但key的两侧出现了双引号,虽不影响读取,但会占用一定的空间,对大量数据的情况造成不必要的开销,因此,推荐对key使用第二种序列化方式,即StringRedisSerializer,将key转换为String进行存储。除此之外,并没有太多的问题。

修改key的序列化器代码如下:

//设置redis key的序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());

再次运行代码,redis中存储的key就不再带有双引号了。

image-20240302160747268

2.写入对象数据

首先构造一个实体类UserVO,用于稍后作为对象传输。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserVO {
    private Integer id;
    private String username;
}

我们修改存入redis缓存代码,新建一个UserVO对象并存入。

//构造对象
UserVO userVO =new UserVO(1,"橘生淮南");
//设置redis缓存
redisTemplate.opsForValue().set("user",userVO);

存储结果如下:

image-20240302162235016

可以看到,我们的UserVO对象成功存入了Redis中。

但我们可以发现,存入的数据中多了一条名为**"@class"的数据**,这条数据实际上是我们传入的对象的类的字节码,该字节码将会用于反序列化操作,如果不存储该字节码,序列化器在反序列化的时候就不知道这条数据对应的是哪个类,也就无法转换为原本的对象。

同样的,我们也可以发现,对于我们给出的这个对象,其字节码的长度实际上比我要存储的数据的长度还要长,或者说,字节码占用的空间比较大,对于大量数据的情况下,其开销较大。因此,为了节省空间,我们可以采用第二种序列化方式StringRedisSerializer对对象转化为字符串的形式进行存储。

②StringRedisSerializer:将数据序列化成字符串

通过StringRedisSerializer序列化器对对象进行存储,就是单纯的存储字符串,其要求传入的数据类型均为String类型。这就带来了一个问题,不论是序列化还是反序列化都将无法自动完成,必须要我们手动进行。

在Spring中,默认提供了一个名为StringRedisTemplate的类,其key和value的默认序列化方式就是String,因此我们直接使用自动装配就能使用了,无需再配置RedisTemplate。(即可以删除上面提到的RedisConfiguration了)

自动装配:

//装配String序列化器的redis
@Autowired
private StringRedisTemplate stringRedisTemplate;

存储数据的代码:

//构造对象
UserVO userVO =new UserVO(1,"橘生淮南");
//手动序列化为json
String userVoStr = JSON.toJSONString(userVO);//import com.alibaba.fastjson.JSON;
//设置redis缓存
stringRedisTemplate.opsForValue().set("user",userVoStr);

再次查看redis中的数据:

image-20240302164220165

可以发现此时存储的数据已经不存在字节码了,达到了我们想要的效果。

我们从redis中读取user的值:

//取回redis缓存
String user = stringRedisTemplate.opsForValue().get("user");
//手动反序列化为对象
UserVO object = JSON.parseObject(user, UserVO.class);
System.out.println(object);

可以看到,数据均正常输出。

image-20240302164937707

三、总结

综上,建议对key和value都使用StringRedisSerializer序列化器(通过StringRedisTemplate自动装配)进行处理,并手动实现数据的序列化与反序列化。

  • 15
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值