RedisTemplate、StringRedisTemplate、序列化器配置

Lettuce和Jedis

RedisTemplate是SpringDataRedis中对JedisApi的高度封装,提供了Redis各种操作、 异常处理及序列化,支持发布订阅。

首先我们要知道SpringData是Spring中数据操作的模块,包括对各种数据库的集成,比如我们之前学过的Spring Data JDBC、JPA等,其中有一个模块叫做Spring Data Redis,而RedisTemplate就是其中提供操作Redis的通用模板

Spring Data Redis中提供了如下的内容:

1、对不同Redis客户端的整合(Lettuce和Jedis

2、提供了RedisTemplate统一API操作Redis

3、⽀持Redis订阅发布模型

4、⽀持Redis哨兵和集群

5、⽀持基于Lettuce的响应式编程(底层就是Netty

6、⽀持基于JDK、JSON、字符串、Spring对象的数据序列化、反序列化

使用Spring Data Redis需要引入RedisTemplate依赖和commons-pool连接池依赖,Jedis与RedisTemplate底层使用的连接池都是commons-pool2,所以需要导入它

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>

这⾥我们可以看⼀下spring-boot-starter-data-redis底层,发现并没有引入Jedis

原因:

在SpringBoot 2.x版本以后,从原来的Jedis替换成了lettuce,所以2.x以后开始默认使用Lettuce作为Redis客户端,Lettuce客户端基于Netty的NIO框架实现,只需要维持单一的连接(非阻塞式IO)即可高校支持业务端并发请求。同时,Lettuce支持的特性更加全面,其性能表现并不逊于,甚至优于Jedis。

简单理解:

  • Jedis:
    采用的直连,多个线程操作不安全,如果想要避免线程安全问题,就需要使用JedisPool连接池,但是也会有一些线程过多等其他问题,类似于BIO(阻塞式IO)
  • Lettuce:
    底层采用Netty,实例可以在多个线程中进行共享,不存在线程安全问题!类似NIO

默认的RedisTemplate测试

@SpringBootTest
class RedisTestApplicationTests { @Autowiredprivate RedisTemplate redisTemplate;@Testvoid contextLoads() {redisTemplate.opsForValue().set("CSDN","青秋.");System.out.println(redisTemplate.opsForValue().get("CSDN"));}
}

通过指令来查看发现是乱码,这就涉及到了序列化的问题了。

想要解决以上问题,需要了解RedisTemplate序列化的问题,首先进入RedisTemplate源码,发现需要设置key、hashKey和value、hashValue的序列化器

再往下看有一个默认的序列化器

也就是说,RedisTemplate默认采用的是默认的JDK序列化器,这种序列化方式会有一定的问题 比如可读性差、内存占用大

所以总结来说,我们可以修改key和value的RedisSerializer具体实现,这⾥我们可以先看⼀下 RedisSerializer的实现类有哪些:

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

各个序列化器性能测试对比

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

测试结果

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

自定义RedisTemplate

新建RedisConfig配置类,以下是固定模板,可以直接用

这个模板我们采用的Json序列化Value,String序列化Key

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String,Object>
redisTemplate(RedisConnectionFactory factory){// 为了研发⽅便 key直接为String类型RedisTemplate<String,Object> template = new RedisTemplate<>();// 设置连接⼯⼚template.setConnectionFactory(factory);//设置key序列化 用的string序列化template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());//序列化配置,通过JSON解析任意对象GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();//设置value序列化,采用的是Json序列化方式template.setValueSerializer(jsonRedisSerializer);template.setHashKeySerializer(jsonRedisSerializer);template.afterPropertiesSet();return template;}
}

Json序列化Value + RedisTemplate测试

@SpringBootTest
class RedisTestApplicationTests {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Testvoid contextLoads() {redisTemplate.opsForValue().set("CSDN","青秋.");System.out.println(redisTemplate.opsForValue().get("CSDN"));}
}

此时用keys * 查看,没有乱码。那么再储存一个对象试试!

@Test
void saveUser(){redisTemplate.opsForValue().set("stringredistemplate",new User("Mask",20));System.out.println(redisTemplate.opsForValue().get("stringredistemplate"));
}

用可视化工具查看,发现JSON序列化Value后多了个@Class字段

虽然实现了对象的序列化和反序列化,但这是因为添加了@class字段,会导致额外的内存开销,在数据量特别大的时候就会有影响,但是如果没有@class就不会实现自动序列化和反序列化

实际开发中,如果为了节省空间,并不会完全使用JSON序列化来处理value, 而是统一采用String序列化器,储存Java对象也是如此,这就意味着我们需要重新编写RedisTemplate,但是SpringBoot其实提供了一个String序列化器实现的StringRedisTemplate,通过它可以完成以上的需求。

String序列化Value + StringRedisTemplate测试 

@SpringBootTest
class RedisTestApplicationTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;//Json⼯具private ObjectMapper mapper = new ObjectMapper();@Testvoid StringTemplate() throws JsonProcessingException {User user = new User("青秋",18);//⼿动序列化String json = mapper.writeValueAsString(user);//写⼊数据stringRedisTemplate.opsForValue().set("stringredistemplate",json);//读取数据String val =
stringRedisTemplate.opsForValue().get("stringredistemplate");//反序列化User u = mapper.readValue(val,User.class);System.out.println(u);}
}

总结

  • RedisTemplate的Key和Value的序列化器可以根据需要分别设置。
  • RedisTemplate默认使用JdkSerializationRedisSerializer存入数据,会将数据先序列化成字节数组然后在存入Redis数据库,这种value不可读。
  • 如果数据是Object类型,取出的时候又不想做任何的数据转换直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。
  • 当然任何情况下从Redis获取数据的时候,都会默认将数据当做字节数组转化,这样就会导致一个问题:当需要获取的数据不是以字节数组存在redis当中,而是正常的可读的字符串的时候,RedisTemplate就无法获取数据,获取到的值是NULL。这时就需要用StringRedisTempate或者专门设置RedisTemplate的序列化器!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/50949.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter——全网最精致木鱼APP可上架应用市场

研发背景 工作之余&#xff0c;闲来无事&#xff0c;想着研发一款用户可能会经常用到的一款APP,并且能够顺便掌握一下Flutter Material Design 3 UI&#xff0c;所以就有了这款比较精致的木鱼APP的诞生。 开源代码 https://github.com/z244370114/woodenfish

语义分割介绍

1. 定义 语义指具有人们可用语言探讨的意义&#xff0c;分割指图像分割。 语义分割(semantic segmentation)能够将整张图的每个部分分割开&#xff0c;使每个部分都有一定类别意义&#xff08;语义&#xff09;&#xff0c;让计算机可以理解图像。 语义分割是以描边的形式&…

【初阶数据结构篇】顺序表和链表算法题

文章目录 顺序表算法题移除元素删除有序数组中的重复项合并两个有序数组 链表算法题移除链表元素反转链表链表的中间结点合并两个有序链表链表分割链表的回文结构 顺序表算法题 不熟悉顺序表的可以先了解一下 顺序表实现方法 移除元素 给你一个数组 nums 和一个值 val&#x…

基于Xejen框架实现的C# winform鼠标点击器、电脑按键自动点击器的软件开发及介绍

功能演示 文章开始之前&#xff0c;仍然是先来个视频&#xff0c;以便用户知道鼠标连点器的基本功能 软件主界面 多功能鼠标连点器 快速点击&#xff1a; 痕即鼠标点击器可以设定每秒点击次数&#xff0c;让您轻松应对高频点击需求。 切换时长&#xff0c;即每次动作之间的间…

【安卓】Android Studio简易计算器(实现加减乘除,整数小数运算,正数负数运算)

目录 前言 运算效果 一、创建一个新的项目 二、编写xml文件&#xff08;计算器显示页面&#xff09; 三、实现Java运算逻辑 ​编辑 完整代码 xml文件代码&#xff1a; Java文件代码&#xff1a; 注&#xff1a; 前言 随着移动互联网的普及&#xff0c;手机应用程序已…

Linux_基础

文件结构 Linux的文件结构是一个倒的树状图&#xff0c;具体结构如下&#xff1a; bin&#xff1a;存放二进制文件 boot&#xff1a;存放系统启动文件 dev&#xff1a;存放设备文件 etc&#xff1a;存放系统管理时要用到的各种配置文件和子目录 lib&#xff1a;存放系统动…

【Vue2】3-使用Vue脚手架

目录 初始化脚手架 说明 具体步骤 模板项目的结构 关于不同版本的Vue vue.config.js配置文件 ref属性 配置项props mixin&#xff08;混入&#xff09; 插件 scoped样式 总结TodoList案例 webStorage&#xff08;浏览器本地存储&#xff09; TodoList本地存储 组…

【初阶数据结构篇】栈的实现(赋源码)

文章目录 栈1 代码位置2 概念与结构1.1概念1.2结构 2 栈的实现2.1 栈的初始化和销毁2.1.1 初始化2.1.2 销毁 2.2 栈顶插入和删除数据2.2.1 栈顶插入数据&#xff08;压栈&#xff09;2.2.2 栈顶删除数据&#xff08;出栈&#xff09; 2.3 返回栈顶数据2.4 返回栈的有效数据个数…

嵌入式人工智能(31-基于树莓派4B的气压传感器-BMP280)

1、气压传感器 气压传感器&#xff08;Pressure Sensor&#xff09;是一种用于测量气体压力的装置。它可以将气体压力转换为电信号输出&#xff0c;进而实现对气体压力的监测和控制。气压传感器广泛应用于工业自动化、气象观测、建筑监测、航空航天等领域。 气压传感器的工作…

未来的智能农业:智能合约如何提升农业生产效率和可持续性

随着全球人口的增长和资源的有限性&#xff0c;农业生产面临着越来越大的挑战。如何在提高生产效率的同时保障可持续发展成为全球农业发展的关键问题。智能合约作为一种基于区块链技术的自动化执行合约&#xff0c;正在逐渐应用于农业领域&#xff0c;为农业生产带来了新的机遇…

Redis:RDB持久化

1. 简介 实现类似照片记录效果的方式&#xff0c;就是把某一时刻的数据和状态以文件的形式写到磁盘上&#xff0c;也就是 快照。这样一来即使故障宕机&#xff0c;快照文件也不会丢失&#xff0c;数据的可靠性也就得到了保证。 这个快照文件就称为RDB文件(dump.rdb)&#xff0c…

从代码层面熟悉UniAD,开始学习了解端到端整体架构

0. 简介 最近端到端已经是越来越火了&#xff0c;以UniAD为代表的很多工作不断地在不断刷新端到端的指标&#xff0c;比如最近SparseDrive又重新刷新了所有任务的指标。在端到端火热起来之前&#xff0c;成熟的模块化自动驾驶系统被分解为不同的独立任务&#xff0c;例如感知、…

数据倾斜优化思路实践

数据倾斜&#xff0c;顾名思义&#xff0c;就是在计算过程中数据分散度不够&#xff0c;导致某个节点数据过于集中&#xff0c;从而导致任务执行效率大大降低。参照对比下MR的整体流程和ODPS&#xff0c;整体结合理解数据倾斜发生的几个生命周期的节点&#xff0c;如下图&#…

WordPress设置固定连接后提示404

WordPress设置固定链接后出现404错误通常是因为服务器的伪静态规则没有正确设置。以下是几种常见的服务器环境下的解决方案&#xff1a; 宝塔面板&#xff1a;如果服务器安装了宝塔面板&#xff0c;可以在宝塔面板中选择对应的WordPress伪静态规则并保存设置 。 Apache服务器&a…

Linux——DNS服务搭建

&#xff08;一&#xff09;搭建nginx 1.首先布置基本环境 要求能够ping通外网&#xff0c;有yum源 2.安装nginx yum -y install nginx 然后查看验证 3.修改网页配置文件 修改文件&#xff0c;任意编写内容&#xff0c;然后去物理机测试 &#xff08;二&#xff09;创建一…

C++知识点总结:2.类和对象(自用)

类和对象 1. 类和对象的关系2. 对象指针3. 在堆上创建对象4. 成员访问限定符5. 名字编码&#xff08;Name Mangling&#xff09;6.构造函数7.构造函数的重载8.初始化列表8. 成员变量初始化的顺序&#xff08;通过初始化列表&#xff09;9. 初始化 const 成员变量10. 析构函数11…

【机器学习】pytorch 常用函数解析

目录 一、基本函数介绍 1.1 nn.Module 类 1.2 nn.Embedding 1.3 nn.LSTM 1.4 nn.Linear 1.5 nn.CrossEntropyLoss 1.6 torch.save 1.7 torch.load 1.8 nn.functional 1.9 nn.functional.softmax 本文主要对 pytorch 中用到的函数进行介绍&#xff0c;本文会不断更新~…

C语言内存函数精讲

目录 引言 1.内存分配函数malloc 2.内存释放函数free 3.内存拷贝函数memcpy 4.内存移动函数memmove 5.内存设置函数memset 6.内存比较函数memcmp 总结 引言 在C语言编程中&#xff0c;内存管理是核心技能之一。C语言提供了一系列内存操作函数&#xff0c;这些函数在动…

jmeter-beanshell学习-try处理异常

有时候代码执行过程中&#xff0c;出现一些不能处理的情况&#xff0c;就会报错&#xff0c;还影响之后的代码执行&#xff0c;就需要跳过异常。 上面这情况报错了&#xff0c;还影响了下面的打印。beanshell用try和catch处理异常&#xff0c;下面是try的用法&#xff0c;和if有…

技术守护尊严||Chat GPT在抵抗性骚扰的作用分析

就在本周&#xff0c;中国人民大学女博士实名举报导师性骚扰的事情&#xff0c;引发全网关注&#xff01; 性骚扰&#xff0c;无论在线上还是线下&#xff0c;无论在职场还是校园&#xff0c;都是对个人尊严与权益的严重侵犯。 幸运的是&#xff0c;随着人工智能技术的飞速发…