当前位置: 首页 > news >正文

RedisTemplate 中序列化方式辨析

在Spring Data Redis中,RedisTemplate 是操作Redis的核心类,它提供了丰富的API来与Redis进行交互。由于Redis是一个键值存储系统,它存储的是字节序列,因此在使用RedisTemplate时,需要指定键(Key)和值(Value)的序列化方式。不同的序列化方式适用于不同的场景。下面将详细介绍几种序列化方法。

序列化如下对象

User 类

public class User implements Serializable {String name;String ID;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", ID='" + ID + '\'' +'}';}public User(String name, String ID) {this.name = name;this.ID = ID;}public User() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getID() {return ID;}public void setID(String ID) {this.ID = ID;}
}

JdkSerializationRedisSerializer

JdkSerializationRedisSerializer 是使用JDK自带的序列化机制(ObjectOutputStream 和 ObjectInputStream)来序列化和反序列化POJO对象。这种序列化方式会将对象转换成字节序列,并存储在Redis中。这是RedisTemplate中默认的序列化策略之一(但通常不是推荐用于生产环境的默认策略,因为JDK序列化通常效率较低且生成的字节序列较大)。最大的缺点就是:要求序列化的对象要求继承Serializable类,这是DTO无法容忍的一个要求。

优点:
  • 与其他两个比几乎没有优点,超级不推荐!
缺点:
  • 二进制形式存储,不利于查看!94 bytes
  • 序列化生成的字节序列较大,导致网络传输和存储成本较高。
  • 序列化速度慢。
  • 序列化的字节序列是私有的,不便于跨语言或跨平台共享。
代码示例
@Testpublic void test4(){User user = new User("李白","123456");//        GenericToStringSerializer<Object> genericToStringSerializer = new GenericToStringSerializer<>(Object.class);
//        redisTemplate.setKeySerializer(genericToStringSerializer);
//        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
//        redisTemplate.setValueSerializer(jdkSerializationRedisSerializer);redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setValueSerializer(RedisSerializer.java());// 记录开始时间Instant start = Instant.now();redisTemplate.opsForValue().set("test4",user);User user2 = (User)redisTemplate.opsForValue().get("test4");logger.info(user2.toString());// 记录结束时间Instant end = Instant.now();// 计算运行时间long duration = Duration.between(start, end).toMillis();logger.info(duration+"ms");}

在这里插入图片描述

StringRedisSerializer

StringRedisSerializer 是最简单的序列化器,它直接将字符串(或任何可以转换为字符串的数据)作为字节序列存储,不需要进行任何特殊的序列化操作。它适用于键或值为字符串的场景。

优点:
  • 效率高,不需要额外的序列化/反序列化开销。
  • 易于理解和维护。
缺点:
  • 只能用于字符串数据。

Jackson2JsonRedisSerializer

Jackson2JsonRedisSerializer 是基于Jackson库实现的JSON序列化器,它可以将Java对象序列化成JSON格式的字符串,并存储在Redis中。Jackson是一个流行的JSON处理库,提供了丰富的API来序列化和反序列化Java对象。

优点:
  • User 对象不需要实现 Serializable接口。
  • 生成的JSON格式易于阅读和调试。
  • 序列化后的数据相对较小,传输和存储效率较高,64 bytes。
  • 支持复杂的Java对象,包括嵌套对象和集合。
@Test
public void test3(){User user = new User("李白","123456");redisTemplate.setKeySerializer(RedisSerializer.string());
//        Jackson2JsonRedisSerializer<User> userJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(User.class);
//        redisTemplate.setValueSerializer(userJackson2JsonRedisSerializer);redisTemplate.setValueSerializer(RedisSerializer.json());// 记录开始时间Instant start = Instant.now();redisTemplate.opsForValue().set("test3",user);User user2 = (User)redisTemplate.opsForValue().get("test3");logger.info(user2.toString());// 记录结束时间Instant end = Instant.now();// 计算运行时间long duration = Duration.between(start, end).toMillis();logger.info(duration+"ms");
}

在这里插入图片描述

GenericFastJsonRedisSerializer

GenericFastJsonRedisSerializer 是基于Fastjson库实现的JSON序列化器,与JacksonJsonRedisSerializer类似,但它使用的是Fastjson库。Fastjson是另一个流行的JSON处理库,以其高性能著称。

优点:
  • 序列化性能高。
  • 支持复杂的Java对象。
  • 生成的JSON格式易于阅读和调试。
缺点:
  • 可能存在安全漏洞(历史版本中曾发现过安全问题,使用时需注意版本),据测试,FastJson性能不能完全超过Json库,建议生产中别用!。
    @Testpublic void test5(){User user = new User("杜甫","123456");redisTemplate.setKeySerializer(RedisSerializer.string());GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer();redisTemplate.setValueSerializer(genericFastJsonRedisSerializer);// 记录开始时间Instant start = Instant.now();redisTemplate.opsForValue().set("test5",user);User user2 = (User)redisTemplate.opsForValue().get("test5");logger.info(user2.toString());// 记录结束时间Instant end = Instant.now();// 计算运行时间long duration = Duration.between(start, end).toMillis();logger.info(duration+"ms");}

在这里插入图片描述

总结

  • 可读性:JacksonJsonRedisSerializerGenericFastJsonRedisSerializer 皆可
  • 内存占用:GenericFastJsonRedisSerializer 59 bytes 小于 JacksonJsonRedisSerializer 60 bytes 小于 JdkSerializationRedisSerializer 94 bytes。
  • 耗时:JacksonJsonRedisSerializerGenericFastJsonRedisSerializer 差不多 且 都比 JdkSerializationRedisSerializer

生产环境中,无脑选择JacksonJsonRedisSerializer即可!

总的来说,在选择序列化器时,应根据具体的应用场景和需求来决定使用哪种序列化方式。对于大多数基于Spring Boot和Spring Data Redis的项目,推荐使用JacksonJsonRedisSerializer 来序列化和反序列化Java对象,因为它们提供了灵活性和高性能。

嵌套对象测试

    public Map<String, List<User>> getNestedObj(){ArrayList<User> users = new ArrayList<>();for (int i = 0; i < 100; i++) {users.add(new User(UUID.randomUUID().toString().substring(0,8),UUID.randomUUID().toString()));}HashMap<String, List<User>> nestedObj = new HashMap<>();nestedObj.put("one",users);return nestedObj;}
JdkSerializationRedisSerializer
    @Testpublic void test11(){Map<String, List<User>> nestedObj = getNestedObj();redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setValueSerializer(RedisSerializer.java());// 记录开始时间Instant start = Instant.now();redisTemplate.opsForValue().set("test11",nestedObj);// 记录结束时间Instant end = Instant.now();// 计算运行时间long duration = Duration.between(start, end).toMillis();logger.info(duration+"ms");// 从redis获取nestedObj并反序列化Map<String, List<User>> nestedObj2 = (Map<String, List<User>>)redisTemplate.opsForValue().get("test11");logger.info(nestedObj2.toString());}

在这里插入图片描述

JacksonJsonRedisSerializer
    @Testpublic void test12(){Map<String, List<User>> nestedObj = getNestedObj();redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setValueSerializer(RedisSerializer.json());// 记录开始时间Instant start = Instant.now();redisTemplate.opsForValue().set("test12",nestedObj);// 记录结束时间Instant end = Instant.now();// 计算运行时间long duration = Duration.between(start, end).toMillis();logger.info(duration+"ms");// 从redis获取nestedObj并反序列化Map<String, List<User>> nestedObj2 = (Map<String, List<User>>)redisTemplate.opsForValue().get("test12");logger.info(nestedObj2.toString());}

在这里插入图片描述

GenericFastJsonRedisSerializer
 @Testpublic void test13(){Map<String, List<User>> nestedObj = getNestedObj();redisTemplate.setKeySerializer(RedisSerializer.string());GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer();redisTemplate.setValueSerializer(genericFastJsonRedisSerializer);// 记录开始时间Instant start = Instant.now();redisTemplate.opsForValue().set("test13",nestedObj);// 记录结束时间Instant end = Instant.now();// 计算运行时间long duration = Duration.between(start, end).toMillis();logger.info(duration+"ms");// 从redis获取nestedObj并反序列化Map<String, List<User>> nestedObj2 = (Map<String, List<User>>)redisTemplate.opsForValue().get("test13");logger.info(nestedObj2.toString());}

在这里插入图片描述

相关文章:

RedisTemplate 中序列化方式辨析

在Spring Data Redis中&#xff0c;RedisTemplate 是操作Redis的核心类&#xff0c;它提供了丰富的API来与Redis进行交互。由于Redis是一个键值存储系统&#xff0c;它存储的是字节序列&#xff0c;因此在使用RedisTemplate时&#xff0c;需要指定键&#xff08;Key&#xff09…...

数据结构与算法基础篇--二分查找

必要前提&#xff1a;有序数组 算法简述&#xff1a;通过不断取中间值和目标target值进行比较&#xff08;中间值&#xff1a;mid (left right) / 2&#xff09; 如果目标值等于中间位置的值&#xff0c;则找到目标&#xff0c;返回中间位置如果目标值小于中间位置的值&…...

python xlsx 导出表格超链接

该Python脚本用于从Excel文件中的第一列提取所有超链接并保存到一个文本文件中。首先&#xff0c;脚本导入必要的库并定义输入和输出文件的路径。然后&#xff0c;它确保输出文件的目录存在。接着&#xff0c;脚本加载Excel文件并选择活动工作表。通过遍历第一列的所有单元格&a…...

Data Guard高级玩法:failover备库后,通过闪回恢复DG备库

作者介绍&#xff1a;老苏&#xff0c;10余年DBA工作运维经验&#xff0c;擅长Oracle、MySQL、PG、Mongodb数据库运维&#xff08;如安装迁移&#xff0c;性能优化、故障应急处理等&#xff09; 公众号&#xff1a;老苏畅谈运维 欢迎关注本人公众号&#xff0c;更多精彩与您分享…...

【Unity2D 2022:NPC】制作任务系统

一、接受任务 1. 编辑NPC对话脚本&#xff1a; &#xff08;1&#xff09;创建静态布尔变量用来判断ruby是否接受到任务 public class NPCDialog : MonoBehaviour {// 创建全局变量用来判断ruby是否接到任务public static bool receiveTask false; } &#xff08;2&#xff…...

【C++深度学习】多态(概念虚函数抽象类)

✨ 疏影横斜水清浅&#xff0c;暗香浮动月黄昏 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…...

Ubuntu 安装CGAL

一、什么是CGAL CGAL&#xff08;Computational Geometry Algorithms Library&#xff09;是一个广泛使用的开源库&#xff0c;主要用于计算几何算法的实现。该库提供了一系列高效、可靠和易于使用的几何算法和数据结构&#xff0c;适用于各种应用领域。以下是 CGAL 的主要功能…...

RK3568平台开发系列讲解(网络篇)netfilter框架

🚀返回专栏总目录 文章目录 一、Netfilter 介绍二、netfilter 简单案例三、防火墙功能一、Netfilter 介绍 Linux内核自2.4版本开始引入了Netfilter框架,这是一项重要的网络功能增强。Netfilter框架由Linux内核防火墙和网络维护者 Rusty Russell 所提出和实现。这个作者还基于…...

检测音视频文件的声压

FFmpeg使用 ebur128 滤镜检测声压&#xff0c;EBU R128 是欧洲广播联盟&#xff08;European Broadcasting Union&#xff0c;简称 EBU&#xff09;推荐的音频响度测量和归一化标准。 ffmpeg -i input_video.mp4 -filter_complex ebur128peaktrue -f null --f null -&#xff…...

计算机网络-HTTP常见面试题

目录 1. HTTP是什么&#xff1f;2. HTTP常见的状态码&#xff1f;3. HTTP 常见的字段有哪些&#xff1f;4. GET和POST有什么区别&#xff1a;5. GET 和POST方法都是安全和幂等的吗&#xff1f;6. HTTP缓存技术7. HTTP/1.1相比HTTP/1.0提高了什么性能&#xff1f;8. HTTP/2做了什…...

LNMP搭建Discuz和Wordpress

1、LNMP L:linux操作系统 N&#xff1a;nginx展示前端页面web服务 M&#xff1a;mysql数据库&#xff0c;保存用户和密码&#xff0c;以及论坛相关的内容 P&#xff1a;php动态请求转发的中间件 数据库的作用&#xff1a; 登录时验证用户名和密码 创建用户和密码 发布和…...

java中的构造器

Java 中的构造器&#xff08;也称为构造方法&#xff09;是一种特殊的方法&#xff0c;用于初始化对象的状态。在创建 Java 类的实例时&#xff0c;构造器会被自动调用。 构造器的定义&#xff1a; 构造器的名称必须与类名完全相同。构造器没有返回值类型&#xff0c;甚至不包括…...

机器学习筑基篇,​Ubuntu 24.04 快速安装 PyCharm IDE 工具,无需激活!

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] Ubuntu 24.04 快速安装 PyCharm IDE 工具 描述&#xff1a;虽然在之前我们安装了VScode&#xff0c;但是其对于使用Python来写大型项目以及各类配置还是比较复杂的&#xff0c;所以这里我们还是推…...

从0开始基于transformer进行股价预测(pytorch版本)

目录 数据阶段两个问题开始利用我们的代码进行切分 backbone网络训练效果 感觉还行&#xff0c;没有调参数。源码比较长&#xff0c;如果需要我后续会发&#xff08;因为太长了&#xff01;&#xff01;&#xff09; 数据阶段 &#xff01;&#xff01;&#xff01;注意&#…...

【多GPU训练方法】

一、数据并行 这是最常用的方法。整个模型复制到每个GPU上。训练数据被均匀分割&#xff0c;每个GPU处理一部分数据。所有GPU上的梯度被收集并求平均。通常使用NCCL&#xff08;NVIDIA Collective Communications Library&#xff09;等通信库实现。参数更新 使用同步后的梯度…...

2024年PMP考试备考经验分享

PMP是项目管理领域最重要的认证之一,本身是IT行业比较流行的证书&#xff0c;近几年在临床试验领域也渐渐流行起来&#xff0c;是我周围临床项PM几乎人手一个的证书。 考试时间&#xff1a;PMP认证考试形式为180道选择题&#xff0c;考试时间为3小时50分。 考试计划&#xff…...

MT3046 愤怒的象棚

思路&#xff1a; a[]存愤怒值&#xff1b;b[i]存以i结尾的&#xff0c;窗口里的最大值&#xff1b;c[i]存以i结尾的&#xff0c;窗口里面包含✳的最大值。 &#xff08;✳为新大象的位置&#xff09; 例&#xff1a;1 2 3 4 ✳ 5 6 7 8 9 则ans的计算公式b3b4c4c5c6b7b8b9…...

深入了解代理IP常见协议:区别与选择

代理服务器在网络使用中扮演着重要的角色&#xff0c;是您设备和互联网之间的中间层。它不仅可以增强网络访问的安全性和隐私保护&#xff0c;还可以提供许多灵活的应用。使用代理时&#xff0c;不同的协议类型对数据交换具有不同的规则和特征。常见的代理协议包括HTTP代理、HT…...

【Linux 线程】线程的基本概念、LWP的理解

文章目录 一、ps -L 指令&#x1f34e;二、线程控制 一、ps -L 指令&#x1f34e; &#x1f427; 使用 ps -L 命令查看轻量级进程信息&#xff1b;&#x1f427; pthread_self() 用于获取用户态线程的 tid&#xff0c;而并非轻量级进程ID&#xff1b;&#x1f427; getpid() 用…...

Dify中的工具

Dify中的工具分为内置工具&#xff08;硬编码&#xff09;和第三方工具&#xff08;OpenAPI Swagger/ChatGPT Plugin&#xff09;。工具可被Workflow&#xff08;工作流&#xff09;和Agent使用&#xff0c;当然Workflow也可被发布为工具&#xff0c;这样Workflow&#xff08;工…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...