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

【Redis】Java操作Redis之SpringDataRedis

Redis 支持多种 Java 客户端,以下是一些常见的:

1. Jedis

  • 特点 :
    是 Redis 官方推荐的 Java 客户端,它提供了简单易用的 API,与 Redis 命令一一对应,可以直接使用 Redis 的各种基本操作,如字符串操作(set、get)、哈希操作(hset、hget)等。
    比较轻量级,资源消耗相对较少,适合在对资源要求不高的场景下使用,并且性能较好。
  • 优点 :
    包装了一个完整的 Redis 协议,能够很好地支持 Redis 的数据类型和操作。
    支持 Redis 的持久化、事务、发布 / 订阅等功能,能够满足基本的 Redis 使用需求。
    社区活跃,文档和示例丰富,方便开发者学习和使用。
  • 缺点 :
    需要自己管理连接,没有自动重连机制,如果 Redis 服务器重启或网络中断,需要自己处理重连逻辑。
    对于高并发场景,连接池配置不当可能会导致性能瓶颈,因为需要手动管理连接池的大小和连接的分配。
  • 适用场景 :
    适合 Redis 使用场景较为简单,且对资源消耗和性能要求不是特别苛刻的应用。
    在一些小型项目或者对 Redis 操作不复杂的情况下,可以快速集成和使用。

2. Lettuce

  • 特点 :
    使用了异步、非阻塞的 I/O 操作,能够提供较高的性能,尤其是在高并发场景下表现出色。
    支持 Redis 协议的各个版本,并且能够很好地与 Redis 集群模式和主从模式配合使用,方便在集群环境中进行 Redis 操作。
  • 优点 :
    异步设计使得在处理大量并发请求时能够更有效地利用系统资源,提高了程序的性能和响应速度。
    支持响应式编程模型,可以很好地与 Spring 5 的响应式框架集成,适合构建响应式系统。
    对 Redis 集群的支持较好,能够自动处理节点的添加、删除等集群变化情况。
  • 缺点 :
    学习曲线相对较陡,由于它是基于异步编程模型的,对于习惯了同步编程的开发者来说,可能需要一定的时间来适应。文档和示例相对 Jedis 和 Redisson 等客户端来说还不够完善,可能会在使用过程中一些遇到问题难以快速解决。
  • 适用场景 :
    主要适用于高并发场景,特别是在构建具有高性能要求的分布式系统时,能够充分发挥其异步非阻塞的优势。
    当与 Spring 5 等响应式框架结合使用时,可以构建出更加高效、灵活的响应式应用。

3. Redisson

  • 特点 :
    是一个功能强大的 Redis Java 客户端,它在 Jedis 的基础上进行了封装,提供了更高层次的抽象,使得 Java 开发者可以像使用本地 Java 对象一样使用 Redis 数据结构。
    支持分布式锁、事务、发布 / 订阅、Lua 脚本等 Redis 特性,并且实现了许多分布式场景下的解决方案,如分布式集合、分布式队列等。
  • 优点 :
    提供了丰富的分布式解决方案,使得在分布式系统中使用 Redis 变得更加方便和直观。
    具有良好的文档和示例,易于上手,并且社区支持较好。支持自动重连和重试机制,能够更好地应对网络波动和 Redis 服务器重启等情况。
  • 缺点 :
    由于封装层次较多,可能会带来一定的性能开销,相比 Jedis 等底层客户端,性能稍差。
    对于一些简单的 Redis 操作,使用 Redisson 可能会显得有些繁琐,因为它更侧重于分布式场景下的高级功能。
  • 适用场景 :
    适合在分布式系统中使用 Redis,尤其是在需要实现分布式锁、分布式队列等复杂分布式功能的场景下。当项目需要快速开发分布式相关功能,并且对性能要求不是极其苛刻时,Redisson 是一个不错的选择。

4.SpringDataRedis

Spring Data Redis 是 Spring 提供的一个框架,它让在 Spring 应用里用 Redis 变得超简单。它把底层的 Redis Java 客户端(比如 JedisLettuce)给封装起来,给我们提供了一套统一、好用的 API。

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK.JSON.字符串.Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
在这里插入图片描述

以下链接是Spring官方提供的Spring data Redis中文学习文档: https://springdoc.cn/spring-data-redis/

快速入门

SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单:

1.RedisTemplate

1.1 导入pom坐标

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.7</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.heima</groupId><artifactId>redis-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>redis-demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--common-pool--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--Jackson依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

1.2 application配置文件

spring:redis:host: 192.168.88.100 #这里写你配置的redis主机地址port: 6379 #默认6379password: 1234 #你的密码lettuce:pool:max-active: 8  #最大连接max-idle: 8   #最大空闲连接min-idle: 0   #最小空闲连接max-wait: 1000 #连接等待时间1000ms

1.3 代码测试

@SpringBootTest
public class RedisDemoApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void test() {redisTemplate.opsForValue().set("name", "zhangsan");System.out.println(redisTemplate.opsForValue().get("name"));}

总结
SpringDataRedis的使用步骤:

  • 1、引入spring-boot-starter-data-redis依赖
  • 2、在application.yml配置Redis信息
  • 3、注入RedisTemplate

2.1 自定义序列化方式(编写RedisConfig配置类)

RedisTemplate可以接收任意Object作为值写入Redis,但是写入前会把Object序列化为字节形式,Java默认是采用JDK序列化,得到的结果在图形化界面RESP中看是这样的:
在这里插入图片描述
Spring Data Redis 默认使用 JdkSerializationRedisSerializer 作为序列化器。它会将 Java 对象序列化为字节数组存储到 Redis 中。
这就导致了

  • 可读性差:存储在 Redis 中的数据是二进制字节数组,难以直接阅读和理解
  • 内存占用大:比存放的原始数据长度要大很多

我们可以自定义RedisTemplate的序列化方式,代码如下:

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {//创建redisTemplate对象RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();//配置连接工厂redisTemplate.setConnectionFactory(redisConnectionFactory);//配置JSON序列化工具GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();//设置key的序列化redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setHashKeySerializer(RedisSerializer.string());//设置value的序列化redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);return redisTemplate;}
}

这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:
在这里插入图片描述
整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。但这会带来额外的内存开销。

2. StringRedisTemplate

我们提到过,尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:
在这里插入图片描述
为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。
为了减少内存的消耗,我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们Java程序员自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就在内存中就不用多存储数据了,从而节约我们的内存空间。
在这里插入图片描述
这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。

省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:

@SpringBootTest
public class RedisStringTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void test() {stringRedisTemplate.opsForValue().set("name", "zhangsan");System.out.println(stringRedisTemplate.opsForValue().get("name"));}//ObjectMapper使用前需要引入jackson-databind依赖包private static final ObjectMapper mapper = new ObjectMapper();@Testpublic  void testSaveUser() throws JsonProcessingException {User user = new User("李四", 20);String json = mapper.writeValueAsString(user);//写入数据stringRedisTemplate.opsForValue().set("user",json);//读取数据String jsonUser = stringRedisTemplate.opsForValue().get("user");User user1 = mapper.readValue(jsonUser, User.class);System.out.println(user1);}@Testpublic  void testSaveUser2(){User user = new User("李四", 20);//手动序列化String jsonStr = JSONUtil.toJsonStr(user);//写入数据stringRedisTemplate.opsForValue().set("user", jsonStr);//读取数据String jsonUser = stringRedisTemplate.opsForValue().get("user");//手动反序列化User user1 = JSONUtil.toBean(jsonStr, User.class);System.out.println(user1);}
}

以上我使用了Jacksonhutool的JSONUtil两种方式。

此时我们再来看一看存储的数据,我们就会发现那个class数据已经不在了,节约了我们的空间~
在这里插入图片描述
最后小总结:

RedisTemplate的两种序列化实践方案:

  • 方案一:

    • 自定义RedisTemplate
    • 修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
  • 方案二:

    • 使用StringRedisTemplate
    • 写入Redis时,手动把对象序列化为JSON
    • 读取Redis时,手动把读取到的JSON反序列化为Java对象

    hash结构操作

@SpringBootTest
class RedisStringTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid testHash() {//对应redis当中的 key | field | valuestringRedisTemplate.opsForHash().put("user", "name", "张三");stringRedisTemplate.opsForHash().put("user", "age", "18");//对应redis当中 HGETALL:获取一个hash类型的key中的所有的field和valueMap<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user");System.out.println("entries = " + entries);}
}

好啦,redis在java当中的操作我们就简单演示到这里,至于其他api我们在实战篇再去体会和学习~

相关文章:

  • 高并发?多线程?是一个东西吗?
  • LeetCode 热题 100 189. 轮转数组
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】3.3 异常值识别(Z-score法/IQR法/业务规则法)
  • PostgreSQL 的 ANALYZE 命令
  • R绘图|3分钟复现瑞士“苏黎世大学”Nature全球地图——基于R包ggplot2+sf等
  • 【Linux系统】条件变量
  • gitblit安装教程,搭建一个属于自己的Git版本仓库
  • 湖北理元理律师事务所:法律科技融合下的债务管理实践
  • Unity与Unreal Engine(UE)的深度解析及高级用法
  • 【网络】什么是串口链路(Serial Link)?
  • 文学与社会学是否只是在做解释的工作?
  • 【c++深入系列】:万字详解vector(附模拟实现的vector源码)
  • Oracle OCP认证考试考点详解083系列07
  • photoshop学习笔记2
  • 算法每日一题 | 入门-顺序结构-大象喝水
  • Java基于SaaS模式多租户ERP系统源码
  • JavaScript 性能优化之框架 / 工程层面的优化
  • 【深度学习|学习笔记】深度孪生神经网络Deep Siamese neural network(DSCN)的起源、发展、原理和应用场景(附代码)
  • 招聘绩效效果评估方案与优化路径
  • **面试水货程序员马小帅**
  • 客流持续高位运行,长三角铁路计划增开153列旅客列车
  • 安徽安庆市委书记张祥安调研假日经济和旅游安全工作
  • 研究完蚂蚁搬家,我好像明白了为什么我们总是堵车
  • 高速变道致连环车祸,白车“骑”隔离栏压住另一车,交警回应
  • 魔都眼|买买买,老铺黄金新店开业被挤爆:有人排队5小时
  • 武汉楼市新政:二孩、三孩家庭购买新房可分别享受6万元、12万元购房补贴