springboot系列11、redisTemplate和stringRedisTemplate对比、redisTemplate几种序列化方式比较

1、redisTemplate和stringRedisTemplate对比

  RedisTemplate看这个类的名字后缀是Template,若是了解过Spring如何链接关系型数据库的,大概不会难猜出这个类是作什么的 ,它跟JdbcTemplate同样封装了对Redis的一些经常使用的操做,固然StringRedisTemplate跟RedisTemplate功能相似那么确定就会有人问,为何会须要两个Template呢,一个不就够了吗?其实他们二者之间的区别主要在于他们使用的序列化类。
RedisTemplate使用的是 JdkSerializationRedisSerializer 序列化对象
StringRedisTemplate使用的是 StringRedisSerializer 序列化String

一、StringRedisTemplate

  • 主要用来存储字符串,StringRedisSerializer的泛型指定的是String。当存入对象时,会报错 :can not cast into String。
  • 可见性强,更易维护。若是过都是字符串存储可考虑用StringRedisTemplate。

二、RedisTemplate

  • 能够用来存储对象,可是要实现Serializable接口。
  • 以二进制数组方式存储,内容没有可读性。

2、redisTemplate序列化方式比较

那有没有办法,能够序列化对象,可读性又强呢?java

  • 一、手动转化成json串再存储。取出数据须要反序列化。
  • 二、使用其余序列化方式。

spring-data-redis提供以下几种选择:redis

  • GenericToStringSerializer: 能够将任何对象泛化为字符串并序列化
  • Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer其实是同样的
  • JacksonJsonRedisSerializer: 序列化object对象为json字符串
  • JdkSerializationRedisSerializer: 序列化java对象
  • StringRedisSerializer: 简单的字符串序列化

一、性能测试对比

 @Test
    public void testSerial(){
        UserPO userPO = new UserPO(1111L,"小明_testRedis1",25);
        List<Object> list = new ArrayList<>();
        for(int i=0;i<200;i++){
            list.add(userPO);
        }
        JdkSerializationRedisSerializer j = new JdkSerializationRedisSerializer();
        GenericJackson2JsonRedisSerializer g = new GenericJackson2JsonRedisSerializer();
        Jackson2JsonRedisSerializer j2 = new Jackson2JsonRedisSerializer(List.class);


        Long j_s_start = System.currentTimeMillis();
        byte[] bytesJ = j.serialize(list);
        System.out.println("JdkSerializationRedisSerializer序列化时间:"+(System.currentTimeMillis()-j_s_start) + "ms,序列化后的长度:" + bytesJ.length);
        Long j_d_start = System.currentTimeMillis();
        j.deserialize(bytesJ);
        System.out.println("JdkSerializationRedisSerializer反序列化时间:"+(System.currentTimeMillis()-j_d_start));


        Long g_s_start = System.currentTimeMillis();
        byte[] bytesG = g.serialize(list);
        System.out.println("GenericJackson2JsonRedisSerializer序列化时间:"+(System.currentTimeMillis()-g_s_start) + "ms,序列化后的长度:" + bytesG.length);
        Long g_d_start = System.currentTimeMillis();
        g.deserialize(bytesG);
        System.out.println("GenericJackson2JsonRedisSerializer反序列化时间:"+(System.currentTimeMillis()-g_d_start));

        Long j2_s_start = System.currentTimeMillis();
        byte[] bytesJ2 = j2.serialize(list);
        System.out.println("Jackson2JsonRedisSerializer序列化时间:"+(System.currentTimeMillis()-j2_s_start) + "ms,序列化后的长度:" + bytesJ2.length);
        Long j2_d_start = System.currentTimeMillis();
        j2.deserialize(bytesJ2);
        System.out.println("Jackson2JsonRedisSerializer反序列化时间:"+(System.currentTimeMillis()-j2_d_start));
    }

结果:spring

JdkSerializationRedisSerializer序列化时间:8ms,序列化后的长度:1325
JdkSerializationRedisSerializer反序列化时间:4
GenericJackson2JsonRedisSerializer序列化时间:52ms,序列化后的长度:17425
GenericJackson2JsonRedisSerializer反序列化时间:60
Jackson2JsonRedisSerializer序列化时间:4ms,序列化后的长度:9801
Jackson2JsonRedisSerializer反序列化时间:4数据库

二、性能总结

  • JdkSerializationRedisSerializer序列化后长度最小,Jackson2JsonRedisSerializer效率最高。
  • 若是综合考虑效率和可读性,牺牲部分空间,推荐key使用StringRedisSerializer,保持的key简明易读;value可使用Jackson2JsonRedisSerializer
  • 若是空间比较敏感,效率要求不高,推荐key使用StringRedisSerializer,保持的key简明易读;value可使用JdkSerializationRedisSerializer

三、方案1、考虑效率和可读性,牺牲部分空间

package com.example.demo.config.redisConfig;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(new StringRedisSerializer()); // key的序列化类型

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value的序列化类型
        return redisTemplate;
    }
}

注: new Jackson2JsonRedisSerializer(Object.class)须要指明类型,例如:new Jackson2JsonRedisSerializer(User.class),不然会报错:
json

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.example.demo.bean.User。数组

或者开启默认类型:app

 ObjectMapper objectMapper = new ObjectMapper();
 objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
 objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
 jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

这种方式存储时会自动带上类的全路径,占用部分空间:性能

 

四、方案2、空间敏感,忽略可读性和效率影响

@Configuration
public class RedisConfig {
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(factory);
        redisTemplate.setKeySerializer(new StringRedisSerializer()); // key的序列化类型
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); // value的序列化类型
        return redisTemplate;
    }
}

注:该方式,对象须要实现接口:Serializable测试

五、使用示例

@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
public class RedisTest {
    @Resource
    private RedisTemplate redisTemplate;

    @Test
    public void testRedis1(){
        User user = new User();
        user.setAge(11);
        user.setName("我是小王1");
        redisTemplate.opsForValue().set("user37",user);
        System.out.println(redisTemplate.getValueSerializer());
        System.out.println(redisTemplate.getKeySerializer());
        User result = (User) redisTemplate.opsForValue().get("user37");
        System.out.println(result);
    }
}
相关文章
相关标签/搜索