Redis - RedisTemplate及4种序列化方式深入解读

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,经济版 1GB 1个月
简介: Redis - RedisTemplate及4种序列化方式深入解读

20210216222255282.png


概述

使用Spring 提供的 Spring Data Redis 操作redis 必然要使用Spring提供的模板类 RedisTemplate, 今天我们好好的看看这个模板类 。


RedisTemplate


20210216214431352.png


看看4个序列化相关的属性 ,主要是 用于 KEY 和 VALUE 的序列化 。 举个例子,比如说我们经常会将POJO 对象存储到 Redis 中,一般情况下会使用 JSON 方式序列化成字符串,存储到 Redis 中 。


Spring提供的Redis数据结构的操作类


ValueOperations 类,提供 Redis String API 操作

ListOperations 类,提供 Redis List API 操作

SetOperations 类,提供 Redis Set API 操作

ZSetOperations 类,提供 Redis ZSet(Sorted Set) API 操作

GeoOperations 类,提供 Redis Geo API 操作

HyperLogLogOperations 类,提供 Redis HyperLogLog API 操作


StringRedisTemplate


再看个常用的 StringRedisTemplate

RedisTemplate<K, V> 支持泛型,StringRedisTemplate K V 均为String类型。


org.springframework.data.redis.core.StringRedisTemplate 继承 RedisTemplate 类,使用 org.springframework.data.redis.serializer.StringRedisSerializer 字符串序列化方式。

20210216215349631.png


RedisSerializer 序列化 接口

RedisSerializer接口 是 Redis 序列化接口,用于 Redis KEY 和 VALUE 的序列化

20210216220139708.png

RedisSerializer 接口的实现类 如下

20210216220010707.png


归类一下

  • JDK 序列化方式 (默认)
  • String 序列化方式
  • JSON 序列化方式
  • XML 序列化方式


JDK 序列化方式 (默认)


org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ,默认情况下,RedisTemplate 使用该数据列化方式。


我们来看下源码 RedisTemplate#afterPropertiesSet()


20210216222750703.png

Spring Boot 自动化配置 RedisTemplate Bean 对象时,就未设置默认的序列化方式。

绝大多数情况下,不推荐使用 JdkSerializationRedisSerializer 进行序列化。主要是不方便人工排查数据。

我们来做个测试

20210216222955539.png


运行单元测试


20210216223050702.png



看不懂呀 ,老哥


KEY 前面带着奇怪的 16 进制字符 , VALUE 也是一串奇怪的 16 进制字符 。。。。。


为什么是这样一串奇怪的 16 进制? ObjectOutputStream#writeString(String str, boolean unshared) 实际就是标志位 + 字符串长度 + 字符串内容


KEY 被序列化成这样,线上通过 KEY 去查询对应的 VALUE非常不方便,所以 KEY 肯定是不能被这样序列化的。


VALUE 被序列化成这样,除了阅读可能困难一点,不支持跨语言外,实际上也没还OK。不过,实际线上场景,还是使用 JSON 序列化居多。


String 序列化方式

org.springframework.data.redis.serializer.StringRedisSerializer ,字符串和二进制数组的直接转换


20210216223557311.png

绝大多数情况下,我们 KEY 和 VALUE 都会使用这种序列化方案。


JSON 序列化方式


org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer 使用 Jackson 实现 JSON 的序列化方式,并且从 Generic 单词可以看出,是支持所有类。

public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName) {
      .....
      ..... 
    if (StringUtils.hasText(classPropertyTypeName)) {
      mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, classPropertyTypeName);
    } else {
      mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);
    }
  }


classPropertyTypeName 不为空的话,使用传入对象的 classPropertyTypeName 属性对应的值,作为默认类型(Default Typing) ,否则使用传入对象的类全名,作为默认类型(Default Typing)。


我们来思考下,在将一个对象序列化成一个字符串,怎么保证字符串反序列化成对象的类型呢?Jackson 通过 Default Typing ,会在字符串多冗余一个类型,这样反序列化就知道具体的类型了


20210216230349348.jpg



先说个结论

  • 标准JSON
{
  "id": 100,
  "name": "小工匠",
  "sex": "Male"
}


  • 使用 Jackson Default Typing 机制序列化
{
  "@class": "com.artisan.domain.Artisan",
  "id": 100,
  "name": "小工匠",
  "sex": "Male"
}


示例

测试一把

【配置类】

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        // 创建 RedisTemplate 对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置 RedisConnection 工厂。 它就是实现多种 Java Redis 客户端接入的秘密工厂
        template.setConnectionFactory(connectionFactory);
        // 使用 String 序列化方式,序列化 KEY 。
        template.setKeySerializer(RedisSerializer.string());
        // 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。
        template.setValueSerializer(RedisSerializer.json());
        return template;
    }


【单元测试】

   @Test
    public void testJacksonSerializer() {
        Artisan artisan  = new Artisan();
        artisan.setName("小工匠");
        artisan.setId(100);
        artisan.setSex("Male");
        // set
        redisTemplate.opsForValue().set("artisan", artisan);
    }



【结果】

2021021623020442.png


是不是多了@class 属性,反序列化的对象的类型就可以从这里获取到。

@class 属性看似完美解决了反序列化后的对象类型,但是带来 JSON 字符串占用变大,所以实际项目中,我们很少采用 Jackson2JsonRedisSerializer


XML 序列化方式


org.springframework.data.redis.serializer.OxmSerializer使用 Spring OXM 实现将对象和 String 的转换,从而 String 和二进制数组的转换。 没见过哪个项目用过,不啰嗦了



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
JSON NoSQL Java
Redis入门到通关之Java客户端SpringDataRedis(RedisTemplate)
Redis入门到通关之Java客户端SpringDataRedis(RedisTemplate)
232 0
|
2月前
|
NoSQL 测试技术 Go
【Golang】国密SM2公钥私钥序列化到redis中并加密解密实战_sm2反编(1)
【Golang】国密SM2公钥私钥序列化到redis中并加密解密实战_sm2反编(1)
|
20天前
RedisTemplate序列化的问题
RedisTemplate序列化的问题
13 1
|
29天前
|
NoSQL Redis
redis使用jackson序列化数据配置文件
redis使用jackson序列化数据配置文件
40 5
|
1月前
|
监控 NoSQL Java
在 Spring Boot 中实现 Redis 的发布/订阅功能可以通过 RedisTemplate 和消息监听器来完成
在 Spring Boot 中实现 Redis 的发布/订阅功能可以通过 RedisTemplate 和消息监听器来完成
30 1
|
19天前
|
JSON NoSQL Java
Redis18的Java客户端-StringRedisTemplate,序列化存在的问题,使用StringRedisTemplate解决序列化的方法
Redis18的Java客户端-StringRedisTemplate,序列化存在的问题,使用StringRedisTemplate解决序列化的方法
|
25天前
|
存储 监控 NoSQL
Redis系列学习文章分享---第十二篇(搭建哨兵集群+RedisTemplate连接哨兵+搭建分片集群+-散列插槽+集群伸缩 +故障转移+RedisTemplate访问分片集群)
Redis系列学习文章分享---第十二篇(搭建哨兵集群+RedisTemplate连接哨兵+搭建分片集群+-散列插槽+集群伸缩 +故障转移+RedisTemplate访问分片集群)
49 0
|
25天前
|
存储 NoSQL Java
Redis系列学习文章分享---第二篇(Redis快速入门之Java客户端--Jedis+连接池+SpringDataRedis+RedisTemplate+RedisSerializer+Hash)
Redis系列学习文章分享---第二篇(Redis快速入门之Java客户端--Jedis+连接池+SpringDataRedis+RedisTemplate+RedisSerializer+Hash)
29 0
|
2月前
|
JSON NoSQL Java
SpringDataRedis 操作 Redis,并指定数据序列化器
SpringDataRedis 操作 Redis,并指定数据序列化器
41 1
|
22天前
|
存储 Java
JaveSE—IO流详解:对象输入输出流(序列化及反序列化)
JaveSE—IO流详解:对象输入输出流(序列化及反序列化)