Redis:原理速成+项目实战——Redis的Java客户端

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:Redis:原理速成+项目实战——Redis常见命令(数据结构、常见命令总结)
📚订阅专栏:Redis速成
希望文章对你们有所帮助

Redis的Java客户端

  • 客户端对比
  • Jedis快速入门
  • Jedis连接池
  • 认识SpringDataRedis
  • RedisTemplate快速入门
  • RedisTemplate的RedisSerializer
  • StringRedisTemplate

客户端对比

官方给Java推荐了几个客户端:

客户端优点
Jedis以Redis命令作为方法名称,学习成本低,简单实用。但Jedis实例的线程不安全,多线程环境需要基于连接池来使用
Lettuce(Spring官方默认兼容)Lettuce是基于Netty实现的,支持同步、异步和响应式编程方式,并且线程安全。支持Redis的哨兵模式、集群模式和管道模式
RedissonRedisson是一个基于Redis实现的分布式、可伸缩的Java数据结构集合

我们主要要掌握前两种,Spring的整合能力强,而SpringDataRedis正好整合了Jedis与Lettuce。

Jedis快速入门

Jedis的官网地址:Jedis官网地址
我们先进行一个快速的入门,我们需要进行一个Jedis的单元测试的实验:
1、创建一个maven工程并且引入Jedis依赖以及单元测试依赖:

	<dependencies><!--Jedis--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version></dependency><!--单元测试--><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.7.0</version><scope>test</scope></dependency></dependencies>

2、建立测试类,直接上代码:

package com.wang.test;import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;public class JedisTest {private Jedis jedis;@BeforeEachvoid setUp(){//建立连接,需要传入IP地址和端口号jedis = new Jedis("192.168.177.130", 6379);//设置密码jedis.auth("123456");//选择库jedis.select(0);}@Testvoid testString(){//插入数据,方法名称即为Redis命令名称,比较方便简洁String result = jedis.set("name", "布布");System.out.println("result = " + result);//获取数据String name = jedis.get("name");System.out.println("name = " + name);}@Testvoid testHash(){//插入哈希数据jedis.hset("user:1", "name", "Jack");jedis.hset("user:1", "age", "21");//获取Map<String, String> map = jedis.hgetAll("user:1");System.out.println(map);}@AfterEachvoid tearDown(){//释放资源if (jedis != null){jedis.close();}}
}

过程总结:
1、引入依赖
2、创建Jedis对象,建立连接
3、使用Jedis,方法名与Redis命令一致
4、释放资源

Jedis连接池

Jedis本身线程不安全,且频繁的创建和释放连接会造成性能上的损耗,所以需要使用Jedis的连接池来代替Jedis的直连方式。
官方也提供了这样的一个Jedis连接池的工厂类,这个工厂类的主要作用是设置池的一些配置(最大连接数,最大、最小空闲连接等),并且设置了一个静态get方法,当我们需要一个Jedis对象的时候,就可以在这个类中直接调用这个方法了:

package com.wang.jedis.util;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class JedisConnectionFactory {private static final JedisPool jedisPool;static {//配置连接池JedisPoolConfig poolConfig = new JedisPoolConfig();//最大连接数poolConfig.setMaxTotal(8);//最大空闲连接poolConfig.setMaxIdle(8);//最小空闲连接poolConfig.setMinIdle(0);//设置最长等待时间(ms)poolConfig.setMaxWaitMillis(1000);//创建连接池对象jedisPool = new JedisPool(poolConfig,"192.168.177.130", 6379, 1000, "123456");}//获取Jedis对象public static Jedis getJedis(){return jedisPool.getResource();}
}

以后当我们需要创建Jedis对象的时候就不需要再new了,直接用

jedis = JedisConnectionFactory.getJedis();

即可。

认识SpringDataRedis

SpringData是Spring中数据操作的模块,包含了对各种数据库的集成,其中SpringDataRedis就是对Redis的集成模块,其官网地址:
SpringDataRedis官网地址
其具备的一些特征:
1、提供了对不同Redis客户端的整合(Jedis与Lettuce)
2、提供了RedisTemplate统一API来操作Redis
3、支持Redis的发布订阅模型
4、支持Redis哨兵和Redis集群
5、支持基于Luttuce的响应式编程
6、支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
7、支持基于Redis的JDKCollection实现

SpringDataRedis提供了RedisTemplate工具类,封装了各种对Redis多的操作,并且将不同数据类型的操作API封装到了不同的类型中:

API说明
redisTemplate.opsForValue()操作String类型数据
redisTemplate.opsForHash()操作Hash类型数据
redisTemplate.opsForList()操作List类型数据
redisTemplate.opsForSet()操作Set类型数据
redisTemplate.opsForZset()操作SortedSet类型数据
redisTemplate通用命令

RedisTemplate快速入门

SpringBoot已经提供了对SpringDataRedis的支持,使用很方便,这里进行一些实验:
1、新建SpringBoot类型工程,并引入依赖:

		<!--Redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--连接池依赖--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><!--如果报错,就不要指定版本--><version>2.10.0</version></dependency>

2、配置Redis信息:

spring:data:redis:host: 192.168.177.130port: 6379password: 123456lettuce:pool:max-active: 8max-idle: 8min-idle: 0max-wait: 1000ms

3、注入RedisTemplate:

@Autowired
private RedisTemplate redisTemplate;

4、编写测试类代码:

@Test
void testString() {//写入一个String数据redisTemplate.opsForValue().set("name", "布布");//获取String数据Object name = redisTemplate.opsForValue().get("name");System.out.println("name = " + name);
}

RedisTemplate的RedisSerializer

上述的代码运行完毕以后,我们回到命令行去查看:
在这里插入图片描述
这时候我们可以发现,前面插入的键值对在这里完全乱码了。
这是RedisTemplate的序列化的问题,原理自行去理解,重点是我们不能再用这种序列化了。
因此,我们可以自定义RedisTemplate的序列化方式,并且bean方式注入,代码如下:

package com.wang.redis.config;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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){//创建RedisTemplate对象RedisTemplate<String, Object> template = new RedisTemplate<>();//设置连接工厂template.setConnectionFactory(connectionFactory);//创建JSON序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();//设置Key的序列化template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());//设置value的序列化template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);//返回return template;}}

以上代码需要引入JackSon依赖:

        <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.2</version></dependency>

之后就可以修改一下我们的测试类的template使用方式了:

package com.wang;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;@SpringBootTest
class RedisDemoApplicationTests {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Testvoid testString() {//写入一个String数据redisTemplate.opsForValue().set("name", "布布");//获取String数据Object name = redisTemplate.opsForValue().get("name");System.out.println("name = " + name);}
}

现在已经正常序列化了:
在这里插入图片描述
我们再做个实验,来看看对于一个对象,序列化是如何进行的,转化的json又是怎样的:
1、我们创建一个User类:

package com.wang.redis.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private String name;private Integer age;
}

2、编写测试类:

@Test
void testSaveUser(){//写入数据redisTemplate.opsForValue().set("user:100", new User("布布", 21));//获取数据User user = (User) redisTemplate.opsForValue().get("user:100");System.out.println("user = " + user);
}

运行结果:
在这里插入图片描述

StringRedisTemplate

尽管json的序列化方式可以满足我们的需求,但仍然存在一些问题,为了在反序列化时知道对象的类型,json序列化器会将类的class写入json,存入Redis,会造成内存额外开销。
而StringRedisTemplate可以解决这个问题,编写代码测试:

private static final ObjectMapper mapper = new ObjectMapper();@Test
void testSaveUser() throws JsonProcessingException {//创建对象User user = new User("布布", 21);//手动序列化String json = mapper.writeValueAsString(user);//写入数据stringRedisTemplate.opsForValue().set("user:200", json);//获取数据String jsonUser = stringRedisTemplate.opsForValue().get("user:200");//手动反序列化User user1 = mapper.readValue(jsonUser, User.class);System.out.println("user1 = " + user1);
}

在这里插入图片描述
在这里将RedisTemplate的两种序列化方案总结:
方案一(简单但占空间):
1、自定义RedisTemplate
2、修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
方案二(省内存但复杂):
1、使用StringRedisTemplate
2、写入Redis时手动把对象序列化为JSON
3、读取Redis时,手动把读取JSON反序列化为对象

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

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

相关文章

【网络安全 | XCTF】simple_transfer

考察kali基本工具的使用 方法一 打开文件如图&#xff1a; 存在较多协议&#xff0c;将协议分级&#xff1a; 可以看到DLEP协议占比最大&#xff1a; 将其作为过滤器应用&#xff1a; 搜索DLEP&#xff1a; 并没有有利信息&#xff0c;但观察到多数数据包损坏&#xff1a; 执行…

一语道破爬虫,来揭开爬虫面纱

目录 一、爬虫&#xff08;网络蜘蛛(Spider)&#xff09; 1.1、是什么&#xff1a; 1.2、学习的原因 1.3、用在地方&#xff1a; 1.4、是否合法&#xff1a; 1.5、后果 案例&#xff1a; 二、应用领域 三、Robots协议 四、抓包 4.1、浏览器抓包 4.2、抓包工具 常见…

性能优化-如何提高cache命中率

本文主要介绍性能优化领域常见的cache的命中率问题&#xff0c;旨在全面的介绍提高cache命中率的方法&#xff0c;以供大家编写出性能友好的代码&#xff0c;并且可以应对性能优化领域的面试问题。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &am…

C++图论之强连通图

1. 连通性 什么是连通性&#xff1f; 连通&#xff0c;字面而言&#xff0c;类似于自来水管道中的水流&#xff0c;如果水能从某一个地点畅通流到另一个地点&#xff0c;说明两点之间是连通的。也说明水管具有连通性&#xff0c;图中即如此。 无向图和有向图的连通概念稍有差…

【owt-server】一些构建项目梳理

【owt-server】清理日志&#xff1a;owt、srs、ffmpeg 【owt】p2p client mfc 工程梳理【m98】webrtc vs2017构建带符号的debug库【OWT】梳理构建的webrtc和owt mfc工程 m79的mfc客户端及owt-client

在VMware安装CentOS 7:详细教程

安装准备工作 本地虚拟机&#xff1a;我这里使用的是VMware Workstation 17 Pro centos7系统ISO镜像&#xff1a;我这里使用的是CentOS-7-x86_64-DVD-2009.iso&#xff0c;具体的下载地址是在阿里云官方镜像站&#xff1a;centos-7.9.2009-isos-x86_64安装包下载_开源镜像站-阿…

TV端Web页面性能优化实践

01 背景 随着互联网技术的持续创新和电视行业的高速发展&#xff0c;通过电视观看在线视频已经逐渐成为大众的重要娱乐方式。奇异果App作为在TV设备上用户活跃度最高的应用之一&#xff0c;为广大用户提供了丰富的内容播放服务&#xff0c;除此之外&#xff0c;同样有会员运营、…

Qt QAction添加图片

QAction用的时候&#xff0c;时常需要添加图片&#xff0c;如上图所示&#xff0c;代码如下所示&#xff1a; 测试的图片格式包含png,jpg,bmp,svg&#xff0c;其他未测试

年终跑步总结

第一个365天无间断年 以前也跑步很频繁&#xff0c;但今年是第一次365天未缺勤。年跑步量也是历来个人最多&#xff1a;2900km以上。 连续跑步天数累积超700天了 这里出现的签到天数累加只有666次&#xff0c;因为中间有跑步、但没有到app上签到&#xff0c;实际最近一次停…

RabbitMQ消息确认机制

介绍 在使用RabbitMQ发送消息如果出现消息没有发送到,队列没有接收到情况。需要消息确认来排错。 RabbitMQ发送端确认 ConfirmCallback 确认模式 和 ReturnCallback 未投递到 queue 退回模式 ConfirmCallback 确认模式 是生产者发送消息 被broker接收 会触发ConfirmCallba…

kafka实现延迟消息

背景 我们知道消息中间件mq是支持延迟消息的发送功能的&#xff0c;但是kafka不支持这种直接的用法&#xff0c;所以我们需要独立实现这个功能&#xff0c;以下是在kafka中实现消息延时投递功能的一种方案 kafka实现延时消息 主要的思路是增加一个检测服务&#xff0c;这个检…

条款 12:拷贝对象的所有部分

编译器生成的拷贝函数&#xff08;拷贝构造函数&#xff0c;拷贝赋值运算符&#xff09;&#xff0c;会拷贝对象的所有数据&#xff0c;当你声明自己的拷贝函数时&#xff0c;就是在告诉编译器&#xff0c;默认实现中有你不喜欢的地方。 void logCall(const std::string& …

Apple Unity Plugins 接入GameCenter 崩溃解决方案

目录 问题问题原因解决方案可直接使用的UnityPlugins 问题 调用 GKLocalPlayer.Local.FetchItems() 程序崩溃&#xff0c;报错&#xff1a;Thread 1: EXC_BAD_ACCESS (code257, address0x8000000000000002) 启动崩溃&#xff0c;报错&#xff1a;Library not loaded: rpath/Ap…

【Electron】webview 实现网页内嵌

实现效果&#xff1a; 当在输入框内输入某个网址后并点击button按钮 , 该网址内容就展示到下面 踩到的坑&#xff1a;之前通过web技术实现 iframe 标签内嵌会出现 同源策略&#xff0c;同时尝试过 vue.config.ts 内配置跨域项 那样确实 是实现啦 但不知道如何动态切换 tagert …

sklearn学习的一个例子用pycharm jupyter

环境 运行在jupyter 进行开发。即一个WEB端的开发工具。能适时显示开发的输出。后缀用的是ipynb.pycharm也可以支持。但也要提示按装jupyter. 或直接用andcoda 这里我们用pycharm进行项目创建 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jupyterlab pip ins…

基于Python的电商手机数据可视化分析和推荐系统

1. 项目简介 本项目旨在通过Python技术栈对京东平台上的手机数据进行抓取、分析并构建一个简单的手机推荐系统。主要功能包括&#xff1a; 网络爬虫&#xff1a;从京东获取手机数据&#xff1b;数据分析&#xff1a;统计各厂商手机销售分布、市场占有率、价格区间和好评率&am…

Java进阶(第八期): Java中递归的的使用和递归解决一些算法问题 Java中的异常机制、异常的处理逻辑 自定义异常

文章目录 一、递归1.1 递归的介绍1.2 递归的简单练习1.3 图解递归执行流程&#xff1a;1.4 使用递归完成悲波那契数列1.5 猴子吃桃子问题 二、异常三 、异常的处理逻辑3.1 try catch 捕获异常3.2 throws抛出异常 四、自定义异常 Java进阶&#xff08;第八期&#xff09; 一、递…

科技云报道:开源才是大模型的未来?

科技云报道原创。 一年前&#xff0c;ChatGPT横空出世&#xff1b;7个多月后&#xff0c;Meta宣布开源LLaMA 2&#xff0c;并且可免费商用。 这一天&#xff0c;也成为大模型发展的分水岭。短时间内&#xff0c;LLaMA 2对一些闭源的大模型厂商造成了致命性的打击。 随后&…

SpringMVC源码解析——DispatcherServlet初始化

在Spring中&#xff0c;ContextLoaderListener只是辅助功能&#xff0c;用于创建WebApplicationContext类型的实例&#xff0c;而真正的逻辑实现其实是在DispatcherServlet中进行的&#xff0c;DispatcherServlet是实现Servlet接口的实现类。Servlet是一个JAVA编写的程序&#…

HBase 超大表迁移、备份、还原、同步演练手册:全量快照 + 实时同步(Snapshot + Replication)不停机迁移方案

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…