Redis是一个基于内存的key-value结构数据库,所以Redis的读写性能高。可以用作数据库、缓存和消息中间件。
在 Redis 中,序列化器(Serializer)是用于将数据在存储和读取时进行序列化和反序列化操作,即对数据进行编码和解码。
在 Java 中操作 Redis 可以使用 Redis 客户端库。以下是一些常用的操作方式
方式一:Redis的Java客户端有很多,官方推荐的有三种:
Jedis
Lettuce
Redisson
方式二:Spring Data Redis
Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,可以简化 Redis 操作。在 Spring Boot 项目中还提供了对应的 Starter,即 spring-boot-starter-data-redis
Spring Data Reids 中提供了一个高度封装的类:RedisTemplate,针对Jedis客户端中大量api进行了归类封装,将同一类型的操作封装为operation接口,具体分类如下:
ValueOperations:string类型操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:map类型的数据操作
ListOperations:list类型的数据操作
序列化:Java向Redis写入数据时,会对key以及value进行序列化
反序列化:Java从Redis读取数据时,会对key以及value进行反序列化
进入 RedisTemplate 类,可以看到它继承了 RedisAccessor 类。
进入 RedisAccessor 类,可以看到它实现了 InitializingBean 接口,它是一个 Spring 框架提供的接口,是用于在 Bean 实例化后进行初始化操作。
这个 InitializingBean 接口里面定义了一个方式 afterPropertiesSet() 方法,该方法就是在 Bean 的属性设置完成之后会自动调用该方法 ,可以在这个方法中可以进行一些额外的初始化操作,例如设置序列化器。
接下来,实现类 RedisAccessor 重写了 afterPropertiesSet() 方法,并且只有一行代码,这行代码通过使用断言来判断是否已经配置了 RedisConnectionFactory 对象,如果没有配置,将抛出异常并提示"RedisConnectionFactory is required"。
然后,这个 RedisTemplate 类继承了 RedisAccessor 类,并且重写了 afterPropertiesSet() 这个方法,所以 RedisTemplate 类中的afterPropertiesSet() 才是实现序列化器设置的方法。
在方法中,首先调用了父类 RedisAccessor 的 afterPropertiesSet() 方法,判断是否配置RedisConnectionFactory对象 。
接下来,对 defaultUsed 进行初始化操作,设置其为 false 表示没有使用默认序列化器
接下来,判断默认序列化器(defaultSerializer)是否为空,也就是判断是否自定义了序列化器。如果没有设置,则创建一个 JDK序列化器(JdkSerializationRedisSerializer)对象,并设置为 JDK序列化器为默认序列化器,同时判断JDK序列化器的类加载器(classLoader)是否为空,如果为空,则在JDK序列化器对象的构造器参数中,放入序列化和反序列化所需的类。
接下来,判断 enableDefaultSerializer 是否为 true,也就是说是否开启默认序列化器。如果开启了,则继续判断是否设置了 keySerializer、valueSerializer、hashKeySerializer、hashValueSerializer,如果没有设置,则将这个序列化器设置为默认序列化器(defaultSerializer),并设置 defaultUsed 为true,表示使用了默认序列化器
总的来说,就是当没有自定义初始化序列化器时,默认使用的序列化器是JDK序列化器
被序列化器后序列化后的字符串,是可读性非常差的一串字符。它所带来的优点就是安全性变高,但是同时它也会导致空间占用要比不序列化情况要多。所以序列化虽然保证了数据的安全性,但是也导致空间占用变多。
思路:一般情况下,对 key 进行序列化是没有意义的,如果进行序列化可能导致 key 的长度变长,提高内存使用和存储成本,并且增加了对 key 进行比较和查找的复杂性。所以 key 就无需序列化。而 value 是真正的数据内容,也就是 value 作为重要的数据是需要被序列化进行存储的。
解决方法:自定义一个 Redis 配置类,将 Key 序列化器以及 HashKey 序列化器设置为字符串序列化器(StringRedisSerializer)
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate