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

总结
- 可读性:
JacksonJsonRedisSerializer和GenericFastJsonRedisSerializer皆可 - 内存占用:
GenericFastJsonRedisSerializer59 bytes 小于JacksonJsonRedisSerializer60 bytes 小于JdkSerializationRedisSerializer94 bytes。 - 耗时:
JacksonJsonRedisSerializer和GenericFastJsonRedisSerializer差不多 且 都比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中,RedisTemplate 是操作Redis的核心类,它提供了丰富的API来与Redis进行交互。由于Redis是一个键值存储系统,它存储的是字节序列,因此在使用RedisTemplate时,需要指定键(Key)…...
数据结构与算法基础篇--二分查找
必要前提:有序数组 算法简述:通过不断取中间值和目标target值进行比较(中间值:mid (left right) / 2) 如果目标值等于中间位置的值,则找到目标,返回中间位置如果目标值小于中间位置的值&…...
python xlsx 导出表格超链接
该Python脚本用于从Excel文件中的第一列提取所有超链接并保存到一个文本文件中。首先,脚本导入必要的库并定义输入和输出文件的路径。然后,它确保输出文件的目录存在。接着,脚本加载Excel文件并选择活动工作表。通过遍历第一列的所有单元格&a…...
Data Guard高级玩法:failover备库后,通过闪回恢复DG备库
作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等) 公众号:老苏畅谈运维 欢迎关注本人公众号,更多精彩与您分享…...
【Unity2D 2022:NPC】制作任务系统
一、接受任务 1. 编辑NPC对话脚本: (1)创建静态布尔变量用来判断ruby是否接受到任务 public class NPCDialog : MonoBehaviour {// 创建全局变量用来判断ruby是否接到任务public static bool receiveTask false; } (2ÿ…...
【C++深度学习】多态(概念虚函数抽象类)
✨ 疏影横斜水清浅,暗香浮动月黄昏 🌏 📃个人主页:island1314 🔥个人专栏:C学习 🚀 欢迎关注:👍点赞 &…...
Ubuntu 安装CGAL
一、什么是CGAL CGAL(Computational Geometry Algorithms Library)是一个广泛使用的开源库,主要用于计算几何算法的实现。该库提供了一系列高效、可靠和易于使用的几何算法和数据结构,适用于各种应用领域。以下是 CGAL 的主要功能…...
RK3568平台开发系列讲解(网络篇)netfilter框架
🚀返回专栏总目录 文章目录 一、Netfilter 介绍二、netfilter 简单案例三、防火墙功能一、Netfilter 介绍 Linux内核自2.4版本开始引入了Netfilter框架,这是一项重要的网络功能增强。Netfilter框架由Linux内核防火墙和网络维护者 Rusty Russell 所提出和实现。这个作者还基于…...
检测音视频文件的声压
FFmpeg使用 ebur128 滤镜检测声压,EBU R128 是欧洲广播联盟(European Broadcasting Union,简称 EBU)推荐的音频响度测量和归一化标准。 ffmpeg -i input_video.mp4 -filter_complex ebur128peaktrue -f null --f null -ÿ…...
计算机网络-HTTP常见面试题
目录 1. HTTP是什么?2. HTTP常见的状态码?3. HTTP 常见的字段有哪些?4. GET和POST有什么区别:5. GET 和POST方法都是安全和幂等的吗?6. HTTP缓存技术7. HTTP/1.1相比HTTP/1.0提高了什么性能?8. HTTP/2做了什…...
LNMP搭建Discuz和Wordpress
1、LNMP L:linux操作系统 N:nginx展示前端页面web服务 M:mysql数据库,保存用户和密码,以及论坛相关的内容 P:php动态请求转发的中间件 数据库的作用: 登录时验证用户名和密码 创建用户和密码 发布和…...
java中的构造器
Java 中的构造器(也称为构造方法)是一种特殊的方法,用于初始化对象的状态。在创建 Java 类的实例时,构造器会被自动调用。 构造器的定义: 构造器的名称必须与类名完全相同。构造器没有返回值类型,甚至不包括…...
机器学习筑基篇,Ubuntu 24.04 快速安装 PyCharm IDE 工具,无需激活!
[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] Ubuntu 24.04 快速安装 PyCharm IDE 工具 描述:虽然在之前我们安装了VScode,但是其对于使用Python来写大型项目以及各类配置还是比较复杂的,所以这里我们还是推…...
从0开始基于transformer进行股价预测(pytorch版本)
目录 数据阶段两个问题开始利用我们的代码进行切分 backbone网络训练效果 感觉还行,没有调参数。源码比较长,如果需要我后续会发(因为太长了!!) 数据阶段 !!!注意&#…...
【多GPU训练方法】
一、数据并行 这是最常用的方法。整个模型复制到每个GPU上。训练数据被均匀分割,每个GPU处理一部分数据。所有GPU上的梯度被收集并求平均。通常使用NCCL(NVIDIA Collective Communications Library)等通信库实现。参数更新 使用同步后的梯度…...
2024年PMP考试备考经验分享
PMP是项目管理领域最重要的认证之一,本身是IT行业比较流行的证书,近几年在临床试验领域也渐渐流行起来,是我周围临床项PM几乎人手一个的证书。 考试时间:PMP认证考试形式为180道选择题,考试时间为3小时50分。 考试计划ÿ…...
MT3046 愤怒的象棚
思路: a[]存愤怒值;b[i]存以i结尾的,窗口里的最大值;c[i]存以i结尾的,窗口里面包含✳的最大值。 (✳为新大象的位置) 例:1 2 3 4 ✳ 5 6 7 8 9 则ans的计算公式b3b4c4c5c6b7b8b9…...
深入了解代理IP常见协议:区别与选择
代理服务器在网络使用中扮演着重要的角色,是您设备和互联网之间的中间层。它不仅可以增强网络访问的安全性和隐私保护,还可以提供许多灵活的应用。使用代理时,不同的协议类型对数据交换具有不同的规则和特征。常见的代理协议包括HTTP代理、HT…...
【Linux 线程】线程的基本概念、LWP的理解
文章目录 一、ps -L 指令🍎二、线程控制 一、ps -L 指令🍎 🐧 使用 ps -L 命令查看轻量级进程信息;🐧 pthread_self() 用于获取用户态线程的 tid,而并非轻量级进程ID;🐧 getpid() 用…...
Dify中的工具
Dify中的工具分为内置工具(硬编码)和第三方工具(OpenAPI Swagger/ChatGPT Plugin)。工具可被Workflow(工作流)和Agent使用,当然Workflow也可被发布为工具,这样Workflow(工…...
SAP 利润中心(Profit Center, PCA)深度解析:定义、核算、数据归集与实例
SAP 利润中心(Profit Center, PCA)深度解析:定义、核算、数据归集与实例利润中心是 SAP 管理会计(CO-PCA) 核心组织单元,是面向内部经营考核的虚拟核算主体,可独立计算收入、成本、费用与利润&a…...
PX4 Firmware V1.14.4 开源支持
PX4 官方固件版本迭代迅猛,这往往导致开发者在硬件兼容性、环境搭建及软件依赖性上遭遇重重挑战。为彻底解决这一问题,Kerloud 推出固件与文档长期支持(LTS)计划。我们将对飞控固件代码、技术文档及参数调优指南实施持续性维护&am…...
你的时间序列真的平稳吗?手把手教你用ADF检验(Dickey-Fuller)和滚动统计为预测模型打好基础
时间序列平稳性诊断实战:从理论到Python实现 时间序列分析中,平稳性检验是建模前的关键步骤。许多经典预测模型(如ARIMA)都建立在数据平稳的假设之上。但现实中的时间序列往往带有趋势或季节性,直接建模会导致预测失效…...
报名CSGO/steam游戏搬砖项目前,这些内幕一定要了解
我相信大多数人都经常困惑于一件事,那就是每当想交钱报名某个项目的时候,却发现网上做这个项目的团队很多,一家比一家会吹,一家比一家牛B,着实很难抉择到底选哪家。生怕报名了后迎接自己的就是一个深不见底的黑洞&…...
互联网音频播放器技术演进与Xilinx可编程逻辑应用
1. 互联网音频播放器的技术演进与市场背景2000年初,互联网音频播放器市场正处于爆发式增长的前夜。当时最引人注目的产品当属Diamond Multimedia推出的Rio PMP-300便携式MP3播放器,这款设备彻底改变了人们获取和欣赏音乐的方式。作为第一代互联网音频硬件…...
mitojs高级配置与Hook机制:如何实现高度定制化监控
mitojs高级配置与Hook机制:如何实现高度定制化监控 【免费下载链接】monitor 👀 一款轻量级的收集页面的用户点击行为、路由跳转、接口报错、代码报错、页面性能并上报服务端的SDK 项目地址: https://gitcode.com/gh_mirrors/mo/monitor 在当今We…...
OpenAI Cookbook中文版:AI应用开发实战指南与工程化实践
1. 项目概述:一份面向中文开发者的AI应用开发“菜谱”最近在GitHub上看到一个挺有意思的项目,叫yunwei37/openai-cookbook-zh-cn。简单来说,这就是OpenAI官方那个大名鼎鼎的openai-cookbook仓库的中文翻译版。但如果你觉得它仅仅是个翻译&…...
HCCS:整数优化的Transformer注意力Softmax替代方案
1. 整数优化的HCCS软最大替代方案概述在Transformer架构的多头注意力机制中,Softmax函数长期以来都是计算效率的瓶颈环节。传统Softmax需要进行指数运算和归一化操作,这在低精度整数推理场景下尤为昂贵。我们提出的HCCS(Head-Calibrated Clip…...
PyCharm直连Spark集群:一站式配置与避坑指南
1. 为什么需要PyCharm直连Spark集群? 作为数据工程师,我经常需要在本地开发Spark应用,然后部署到远程集群执行。传统方式是本地写完代码后,手动上传到服务器再用spark-submit提交,这个过程既繁琐又容易出错。直到发现P…...
局域网文件传输终极指南:3步实现跨平台文件秒传
局域网文件传输终极指南:3步实现跨平台文件秒传 【免费下载链接】LAN-Share Cross platform LAN File transfer application built with Qt C framework 项目地址: https://gitcode.com/gh_mirrors/la/LAN-Share 还在为电脑间传文件而烦恼吗?U盘太…...
