spring data redis 序列化

       一直在项目中使用redis,偶然遇到一个问题,你们项目中的redis用的是那种序列化?回想一下确实也没太注意,学艺不精,所以在网上查阅了资料,做一下总结。

       一般在工作中使用redis存储的api都是使用spring data redis的 RedisTemplate 和 StringRedisTemplate,为啥spring提供了两个template呢,其实这里面是有点文章的。

RedisTemplate 和 StringRedisTemplate 的区别呢,主要在与序列化,StringRedisTemplate存储的key-val,用RedisTemplate去(操作)get(key)是取不出来的。RedisTemplate存储的key-val,用StringRedisTemplate去(操作)get(key)也是取不出来的。为啥呢?

来段RedisTemplate的源码:

private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();  
  
private RedisSerializer keySerializer = null;  
private RedisSerializer valueSerializer = null;  
private RedisSerializer hashKeySerializer = null;  
private RedisSerializer hashValueSerializer = null;  
private RedisSerializer<String> stringSerializer = new StringRedisSerializer();  
if (this.enableDefaultSerializer) {
            if (this.keySerializer == null) {
                this.keySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.valueSerializer == null) {
                this.valueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashKeySerializer == null) {
                this.hashKeySerializer = this.defaultSerializer;
                defaultUsed = true;
            }

            if (this.hashValueSerializer == null) {
                this.hashValueSerializer = this.defaultSerializer;
                defaultUsed = true;
            }
        }

当没有指定RedisTemplate的key/value/hashValue...序列化的时候,默认是使用 JdkSerializationRedisSerializer;   

JdkSerializationRedisSerializer在存储时会转成字节数组进行存储;

 

对于 key = "AAAA"  value = "cccc" 的情况, server 端运行的情况如下

 "SET" "\xac\xed\x00\x05t\x00\x04AAAA" "\xac\xed\x00\x05t\x00\x04cccc"

 "GET" "\xac\xed\x00\x05t\x00\x04AAAA"

在这种序列化下使用value自增的操作是会报类型错误的。

 

StringRedisTemplate使用的是StringRedisSerializer进行序列化。

 public StringRedisTemplate() {
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        this.setKeySerializer(stringSerializer);
        this.setValueSerializer(stringSerializer);
        this.setHashKeySerializer(stringSerializer);
        this.setHashValueSerializer(stringSerializer);
    }

 StringRedisSerializer在序列化的时候会以String的形式存储

对于 key = "AAAA"  value = "cccc" 的情况, server 端运行的情况如下:

"SET" "AAAA" "cccc"

 "GET" "AAAA"

 

这也造成了RedisTemplate和StringRedisTemplate去操作相互key的时候,结果都是不成功的。

所以为了方便统一一点,都会在RedisTemplate中去配置以String形式存储的序列化

<!-- redis 序列化策略 ,通常情况下key值采用String序列化策略, -->  
<!-- 如果不指定序列化策略,StringRedisTemplate的key和value都将采用String序列化策略; -->  
<!-- 但是RedisTemplate的key和value都将采用JDK序列化 这样就会出现采用不同template保存的数据不能用同一个template操作的问题 -->  
<bean id="stringRedisSerializer"   
    class="org.springframework.data.redis.serializer.StringRedisSerializer" />  
  
<bean id='redisWriteTemplate' class="org.springframework.data.redis.core.RedisTemplate">  
    <property name="connectionFactory" ref="jedisWriteConnectionFactory" />  
    <property name="keySerializer" ref="stringRedisSerializer" />  
    <property name="hashKeySerializer" ref="stringRedisSerializer" />  
</bean>  

这里只指定了部分key的StringRedisSerializer,当然如果需要的话也可以指定value的StringRedisSerializer序列化

<property name="hashKeySerializer" ref="stringSerializer" />  
<property name="hashValueSerializer" ref="stringSerializer"/>

这样配置的话RedisTemplate的 key、val都会以String的形式存储。

相率来说的话JdkSerializationRedisSerializer要比StringRedisSerializer高一些。

一般存储的可能会不仅仅是String类型的对象,那么在存储的时候只需要序列化成json串存储就可以了,然后get出来之后再把json串解析成相应的对象。

当然也不仅仅只有这两种序列化,spring还提供了其他几种。这两种最常用一些。有兴趣的可以再深入理解,小弟就先介绍到这里了。

 

如有写的不对的地方,勿喷,还请谅解。

面试题:你们项目中的redis使用的是什么序列化?为什么?几种序列化有什么区别?

 

参考资料:

https://www.cnblogs.com/edwinchen/p/3816938.html

https://blog.csdn.net/xwq911/article/details/50834912

https://blog.csdn.net/y666666y/article/details/70212767

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值