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

一、redisTemplate和stringRedisTemplate对比

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

RedisTemplate使用的是 JdkSerializationRedisSerializer 序列化对象
StringRedisTemplate使用的是 StringRedisSerializer 序列化String

1、StringRedisTemplate

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

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

2、RedisTemplate

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

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

二、redisTemplate序列化方式比较

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

  • 1、手动转化成json串再存储。取出数据需要反序列化。
  • 2、使用其他序列化方式。

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

  • GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
  • Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
  • JacksonJsonRedisSerializer: 序列化object对象为json字符串
  • JdkSerializationRedisSerializer: 序列化java对象
  • StringRedisSerializer: 简单的字符串序列化

1、性能测试对比

@Test
    public void testSerial(){
        UserPO userPO = new UserPO(1111L,"小明_testRedis1",25);
        List list = new ArrayList<>();
        for(int i=0;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));
    }

结果:

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

2、性能总结

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

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

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 getRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        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 ),否则会报错:

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

或者开启默认类型:

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

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

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

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

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

注:该方式,对象需要实现接口:Serializable

5、使用示例

@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);
    }
}

Original: https://www.cnblogs.com/wangzhuxing/p/10198347.html
Author: 小人物的奋斗
Title: springboot系列十一、redisTemplate和stringRedisTemplate对比、redisTemplate几种序列化方式比较

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529348/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • shell中的段落注释

    摘自: 感叹号可以用任意的串和字符替代,比如 注意!和BLOCK之前不能有空格,但是可以用Tab Original: https://www.cnblogs.com/LiuYanY…

    Linux 2023年5月28日
    086
  • shell脚本调试方法

    set -x bash -x test.sh 作者:习惯沉淀 如果文中有误或对本文有不同的见解,欢迎在评论区留言。 如果觉得文章对你有帮助,请点击文章右下角【推荐】一下。您的鼓励是…

    Linux 2023年5月28日
    095
  • Windows批处理一键添加hosts文件

    批处理一键添加hosts文件 此脚本主要用于安装一些学习软件时需屏弊一些网站,双击一键修改。 @echo off echo 获取Administrator权限 cacls.exe …

    Linux 2023年6月8日
    0103
  • NTP和chrony时间同步

    古代计时方式 ●在远古时期,人类用来确定时间的方式是一些自然界”相对”亘古不变的周期。如地球的公转是为一年,月球的公转是为一月,地球的自转是为一天等,最早的…

    Linux 2023年6月7日
    0113
  • vue过滤器和生命周期——day02

    vue之过滤器和生命周期——day02 过滤器: 概念:Vue.js 允许你自定义过滤器, 可被用作一些常见的文本格式化。过滤器可以用在两个地方: mustache 插值和 v-b…

    Linux 2023年6月7日
    0130
  • lab 1

    int father[2],son[2]; int son[2]; if (fork() == 0) { int n; char buf[1]; close(0); dup(fat…

    Linux 2023年6月7日
    075
  • 吴军《浪潮之巅》阅读随笔(二)信息产业的规律性

    在这本书上册的最后一章《信息产业的规律性》中,有几个问题让我很感兴趣。 在信息科技某个领域发展成熟之后,一般在全球容不下三个以上的主要竞争者,这个行业一定有一个老大、是这个行业的主…

    Linux 2023年6月14日
    0134
  • Java动态脚本Groovy,高级啊!

    前言:请各大网友尊重本人原创知识分享,谨记本人博客: 南国以南i 简介: Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编…

    Linux 2023年6月14日
    0142
  • shell脚本中 /dev/null 的用途

    /dev/null 是一个特殊的设备文件,它丢弃一切写入其中的数据 可以将它 视为一个黑洞, 它等效于只写文件, 写入其中的所有内容都会消失, 尝试从中读取或输出不会有任何结果,同…

    Linux 2023年6月13日
    0102
  • 我最鄙视的程序员

    今天在技术群里看到关于优秀程序员特质的话题,让我想起多年前的一个同事,一个我最鄙视的程序员。 他的名字叫李伟(化名),是入职没多久的员工,我所在的开发二组和他在的一组,以前没有过工…

    Linux 2023年6月6日
    090
  • Laxcus远程终端

    Laxcus集群操作系统的远程终端越来越象Linux的VIM了,除了界面风格之外,在用户使用的命令上也在向VIM靠近,原因嘛也不难理解,毕竟Laxcus是一个分布式的操作系统,处理…

    Linux 2023年6月6日
    0119
  • shell脚本中 /dev/null 的用途

    /dev/null 是一个特殊的设备文件,它丢弃一切写入其中的数据 可以将它 视为一个黑洞, 它等效于只写文件, 写入其中的所有内容都会消失, 尝试从中读取或输出不会有任何结果,同…

    Linux 2023年6月13日
    097
  • Danskin’s Theorem

    Statement 1 假设 (\phi(x,z)) 为含有两个变量的连续函数: (\phi : \mathbb{R}^n \times Z \rightarrow \mathbb…

    Linux 2023年6月7日
    089
  • Docker部署Redis

    执行以下命令,创建并启动镜像。如果本地没镜像,会自动拉取 docker run \ -itd \ –restart=always \ –name=redis \ -p 6379…

    Linux 2023年6月7日
    085
  • C盘空间怎么不够了?原来杀毒软件隔离区太大了

    打开小红伞的隔离区,文件全选,删除,居然一下多出20个G. C盘空间怎么不够了?原来杀毒软件隔离区太大了 麻了。打开小红伞的隔离区,文件全选,删除,一下多出20个G. 还有一个比较…

    Linux 2023年6月6日
    0116
  • sed命令

    对文件的操作无非就是”增删改查”,怎样用sed 命令实现对文件的”增删改查”,玩转sed 是写自动化脚本必须的基础之一 sed遵循简…

    Linux 2023年6月13日
    091
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球