深入理解 Redis Template及4种序列化方式

概述

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

RedisTemplate

看看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 字符串序列化方式。

RedisSerializer 序列化 接口

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

RedisSerializer 接口的实现类 如下

归类一下

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

JDK 序列化方式 (默认)

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

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

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

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

我们来做个测试

运行单元测试

看不懂呀 ,老哥

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 ,字符串和二进制数组的直接转换

绝大多数情况下,我们 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 ,会在字符串多冗余一个类型,这样反序列化就知道具体的类型了

先说个结论

标准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);
 }

【结果】

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

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

XML 序列化方式

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

到此这篇关于深入理解 Redis Template及4种序列化方式的文章就介绍到这了,更多相关Redis Template序列化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解决RedisTemplate的key默认序列化器的问题

    redis的客户端换成了spring-boot-starter-data-redis,碰到了一个奇怪的问题, 在同一个方法中 1.先hset,再hget,正常获得数据. 在不同的方法中 先hset,再hget获取不到数据,通过redis的monitor监控发现了命令的问题: 实际我的key为JK_HASH:csrk,hashkey为user,但是根据上图所示,实际执行的命令多了好多其他字符,这是什么原因呢? 在服务器端先确认发现实际有这个Hash,通过hset可以得到正确的数据,所以第一次执行h

  • 深入理解 Redis Template及4种序列化方式

    概述 使用Spring 提供的 Spring Data Redis 操作redis 必然要使用Spring提供的模板类 RedisTemplate, 今天我们好好的看看这个模板类 . RedisTemplate 看看4个序列化相关的属性 ,主要是 用于 KEY 和 VALUE 的序列化 . 举个例子,比如说我们经常会将POJO 对象存储到 Redis 中,一般情况下会使用 JSON 方式序列化成字符串,存储到 Redis 中 . Spring提供的Redis数据结构的操作类 ValueOpera

  • Java实现几种序列化方式总结

    0.前言 本文主要对几种常见Java序列化方式进行实现.包括Java原生以流的方法进行的序列化.Json序列化.FastJson序列化.Protobuff序列化. 1.Java原生序列化 Java原生序列化方法即通过Java原生流(InputStream和OutputStream之间的转化)的方式进行转化.需要注意的是JavaBean实体类必须实现Serializable接口,否则无法序列化.Java原生序列化代码示例如下所示: package serialize; import java.io

  • redis数据的两种持久化方式对比

    一.概念介绍 redis提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Apend Only File). RDB方式 RDB方式是一种快照式的持久化方法,将某一时刻的数据持久化到磁盘中. •redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件.正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的. •对于RDB方式,redis会单独创建(fork)一个子进程来进行持久化,而

  • Java Kryo,Protostuff,Hessian序列化方式对比

    目录 前言 性能对比 前期准备 序列化后字节所占空间大小比较 其他比较 小结 前言 前段时间在写RPC框架的时候用到了Kryo.Hessian.Protostuff三种序列化方式.但是当时因为急于实现功能,就只是简单的的看了一下如何使用这三种序列化方式,并没有去深入研究各自的特性,以及优点和缺点.知道现在就将RPC框架写完了之后,才有时间静下心来对三种方式做一个对比,总结. Kryo.Hessain.Protostuff都是第三方开源的序列化/反序列化框架,要了解其各自的特性,我们首先需要知道序

  • java常见的序列化方式

    在远程调用中,需要把参数和返回值通过网络传输,这个使用就要用到序列化将对象转变成字节流,从一端到另一端之后再反序列化回来变成对象. 既然前面有一篇提到了hessian,这里就简单讲讲Java序列化和hessian序列化的区别. 首先,hessian序列化比Java序列化高效很多,而且生成的字节流也要短很多.但相对来说没有Java序列化可靠,而且也不如Java序列化支持的全面.而之所以会出现这样的区别,则要从它们的实现方式来看. 先说Java序列化,具体工作原理就不说了,Java序列化会把要序列化

  • 详解Redis 分布式锁遇到的序列化问题

    场景描述 最近使用 Redis 遇到了一个类似分布式锁的场景,跟 Redis 实现分布式锁类比一下,就是释放锁失败,也就是缓存删不掉.又踩了一个 Redis 的坑-- 这是什么个情况.又是怎样排查的呢? 本文主要对此做个复盘. 问题排查 既然是释放锁有问题,那就先看看释放锁的代码吧. 释放锁 释放锁使用了 Lua 脚本,代码逻辑和 Lua 脚本如下: 释放锁示例代码 public Object release(String key, String value) { Object existedV

  • Redis Template实现分布式锁的实例代码

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介绍Redis分布式锁实现的博客,然而他们的实现却有着各种各样的问题,为了避免误人子弟,本篇博客将详细介绍如何正确地实现Redis分布式锁. 可靠性 首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 1.互斥性.在任意时刻,只有一个客户端能持有锁. 2.不会发生死锁.即使有一个

  • redis实现的四种常见限流策略

    目录 引言 固定时间窗口算法 实现 滑动时间窗口算法 实现 漏桶算法 实现 令牌桶算法 引言 在web开发中功能是基石,除了功能以外运维和防护就是重头菜了.因为在网站运行期间可能会因为突然的访问量导致业务异常.也有可能遭受别人恶意攻击 所以我们的接口需要对流量进行限制.俗称的QPS也是对流量的一种描述 针对限流现在大多应该是令牌桶算法,因为它能保证更多的吞吐量.除了令牌桶算法还有他的前身漏桶算法和简单的计数算法 下面我们来看看这四种算法 固定时间窗口算法 固定时间窗口算法也可以叫做简单计数算法.

  • 详解基于redis实现的四种常见的限流策略

    目录 一.引言 二.固定时间窗口算法 三.滑动时间窗口算法 四.漏桶算法 五.令牌桶算法 一.引言 在web开发中功能是基石,除了功能以外运维和防护就是重头菜了.因为在网站运行期间可能会因为突然的访问量导致业务异常.也有可能遭受别人恶意攻击 所以我们的接口需要对流量进行限制.俗称的QPS也是对流量的一种描述 针对限流现在大多应该是令牌桶算法,因为它能保证更多的吞吐量.除了令牌桶算法还有他的前身漏桶算法和简单的计数算法 下面我们来看看这四种算法 二.固定时间窗口算法 固定时间窗口算法也可以叫做简单

  • Java之理解Redis回收算法LRU案例讲解

    如何通俗易懂的理解LRU算法? 1.LRU是什么? LRU全称Least Recently Used,也就是最近最少使用的意思,是一种内存管理算法,最早应用于Linux操作系统. LRU算法基于一种假设:长期不被使用的数据,在未来被用到的几率也不大.因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据. LRU算法应用:可以在内存不够时,从哈希表移除一部分很少访问的用户. LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非

随机推荐