SpringBoot Redis入门(一)——redis、Lettuce、Redisson使用

  • 本章:将展示SpringBoot集成Redis三种客户端的配置要点和常见应用示例;
  • 下章:自行实现一个方法级的缓存注解,简化版的Cacheable,使初学者加深对Spring缓存框架的理解。

一、Lettuce客户端

Lettuce 是一种可扩展的、线程安全的 Redis 高级客户端。
从 Spring Boot 2.x 开始, Lettuce 已取代 Jedis 成为SpringBoot 默认的 Redis 客户端。

  • 相比于 Jedis,Lettuce更加全面,并且解决了 Jedis 客户端实例存在非线程安全的问题
  • 支持同步编程,异步编程,响应式编程,自动重新连接,主从模式,集群模块,哨兵模式,管道和编码器等等高级的 Redis 特性
  • Lettuce 底层基于 Netty 框架的事件驱动与 redis 通信,采用了非阻塞的 I/O 操作,可异步调用,相比 Jedis,性能高
  • Lettuce 的 API 是线程安全的,如果不是执行阻塞和事务操作,如 BLPOP 和MULTI/EXEC 等命令,多个线程就可以共享一个连接,性能方面不会衰减。

1.1 pom.xml引入依赖

	<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> </parent><dependencies><!-- redis 缓存操作  默认使用 Lettuce 客户端--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- pool 对象池 Lettuce客户端依赖的插件--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.34</version></dependency><!-- 方便等会写单元测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies>

1.2 application.yml

配置redis服务器配置

spring:redis:# 地址host: localhost# 端口,默认为6379port: 6379# 数据库索引database: 0# 密码password: 123456# 连接超时时间timeout: 10slettuce:pool:# 连接池中的最小空闲连接min-idle: 0# 连接池中的最大空闲连接max-idle: 8# 连接池的最大数据库连接数max-active: 8# #连接池最大阻塞等待时间(使用负值表示没有限制)max-wait: -1ms

1.3 redis缓存应用

UserService.java

@Service
public class UserService {//由于引入redis-starter包,spring已经完成了RedisTemplate 对象创建,什么都不用做就可以直接使用了。@AutowiredRedisTemplate redisTemplate;/*** 最简单的使用,通过key-value方式存取变量;* @param username* @return*/public Object getUserInfo(String username) {//通过用户名从缓存获取用户信息,如果没有即新建并存缓存起来;if (redisTemplate.opsForValue().get(username) == null) {System.out.println("未获取到缓存,新建用户信息.............");Map<String, Object> user = new HashMap<>();user.put("username", username);user.put("usercode", "zhangsan");user.put("sex", "男");user.put("createtime", new Date());redisTemplate.opsForValue().set(username, user);}return redisTemplate.opsForValue().get(username);}//从缓存获取,如果没有则新建,并设置了过期时间为10秒。public Object getUserInfo2(String username) {if (redisTemplate.opsForValue().get(username) == null) {System.out.println("未获取到缓存,新建用户信息.............");Map<String, Object> user = new HashMap<>();user.put("username", username);user.put("usercode", "zhangsan");user.put("sex", "男");user.put("createtime", DateUtils.format(new Date()));redisTemplate.opsForValue().set(username, user);//10秒后过期redisTemplate.expire(username, 10, TimeUnit.SECONDS);}return redisTemplate.opsForValue().get(username);}
}

1.3测试

UserServiceTest.java

    @Testpublic void testRedis() {Object user = userService.getUserInfo("2");System.out.println(user);}

输出:

在这里插入图片描述

给缓存设置过期时间,再来存取。

@Testpublic void testRedisExpire() throws InterruptedException {System.out.println(userService.getUserInfo2("11"));Thread.sleep(1000);System.out.println(userService.getUserInfo2("11"));Thread.sleep(1000);System.out.println(userService.getUserInfo2("11"));Thread.sleep(9000);System.out.println(userService.getUserInfo2("11"));}

输出:
缓存过期时间设置为10秒,当第4次取值时,发现已经过期,自然需要新建对象了。
在这里插入图片描述

二、Redis客户端

Jedis 是一款老牌 Redis 的 Java 客户端,提供了比较全面的 Redis 命令的操作支持,也是目前使用最广泛的客户端。
优点如下:

  • Jedis 的 API 提供了比较全面的 Redis 命令的支持
  • Jedis 中的 Java 方法基本和 Redis 的 API 保持着一致,也就是说了解 Redis 的API,可以熟练的使用 Jedis
  • 支持 pipelining、事务、LUA Scripting、Redis Sentinel、Redis Cluster等等 redis 提供的高级特性
  • 客户端轻量,简洁,便于集成和改造

缺点如下:

  • 使用阻塞的 I/O 操作,且其方法调用都是同步的,程序流需要等到 sockets 处理完 I/O 才能执行,不支持异步
  • Jedis 在实现上是直接连接的 redis server,如果在多线程环境下是非线程安全的,这个时候可以使用连接池来管理 Jedis,已解决 Jedis 客户端实例存在非线程安全的问题
  • 不支持读写分离,需要自己实现

2.1 pom.xml依赖引入

在实际SpringBoot项目中绝大多数情况都不会要求说使用Redis客户端,只有遇到变态需求时可能才会用到吧。不论是用Lettuce 还是用Redis,SpringBoot提供给我们使用的RedisTemplate 接口都是一致的。和Lettuce的差异只是引入的包的差异,SpringBoot已经默认帮我们引入Letucce了,如果要用Redis,那还得排除Letucce的引入,而指定引入Redis。如下:

 <!-- 实现对 Spring Data Redis 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><!-- 去掉对 Lettuce 的依赖,因为 Spring Boot 优先使用 Lettuce 作为 Redis 客户端 --><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!-- 引入 Jedis 的依赖,这样 Spring Boot 实现对 Jedis 的自动化配置 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

代码中使用方法与Lettuce是完成一致的。

三、Redisson

Redisson 是一个在 Redis 的功能基础上实现的 Java 驻内存数据网格客户端。实现了分布式和可扩展的 Java 数据结构,提供很多分布式相关操作服务,例如分布式锁,分布式集合,可通过 Redis 支持延迟队列

Redisson和前两兄弟的区别就像一个用鼠标操作图形化界面,一个用命令行操作文件。Redisson是更高层的抽象,Jedis和Lettuce是Redis命令的封装。

Reddisson 的出现不是又来干一次Redis和Lettuce干过的事儿,而是站在巨人肩膀上干更大的事儿:让猿猿们在分布式场景下也能少掉些头发
优点如下:

  • 实现了分布式特性和可扩展的 Java 数据结构,例如分布式锁,分布式集合,分布式对象,分布式远程调度等等高级功能,适合分布式开发
  • 与 Lettuce 一样,基于 Netty 框架的事件驱动与 redis 通信,支持异步调用,性能高
  • Redisson 的 API 是线程安全的,所以可以使用单个 Redisson 连接来完成各种操作。
  • 支持读写分离,支持读负载均衡,在主从复制和 Redis Cluster 架构下都可以使用
  • 内建 Tomcat Session Manager,为 Tomcat 6/7/8 提供了会话共享功能,可以与 Spring Session 集成,实现基于 Redis 的会话共享
  • 相比于 Jedis、Lettuce 等基于 redis 命令封装的客户端,Redisson 提供的功能更加高端和抽象,Redisson 可以类比 Spring 框架,这些框架搭建了应用程序的基础框架和功能,可以显著提升开发效率,让开发者有更多的时间来关注业务逻辑

所以从应用上讲,Redis和Lettuce能做的是Redisson都能做,其次还能干分布式下的粗活累活。

3.1 依赖引入

Redisson本身是基于Redis做的延伸,所以引入Redisson的时候就已经引入Redis包了,所以只需引入Redisson依赖就可以使用Redis的相关功能了。只是使用上与前面会有差异,效果都一样。

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter </artifactId></dependency><!--使用redisson作为缓存--><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.17.3</version></dependency>

3.2Redisson对象配置

由于没有引入SpringBoot对Redisson的自动配置,这里进行手动配置一下,创建RedissonConfiguration.java

package com.luo.chengrui.labs.lab03.config;import org.redisson.Redisson;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** redis配置*/
@Configuration
public class RedissonConfig extends CachingConfigurerSupport {//创建redisson对象,这是单机版,另外还支持哨兵,和集群。@Bean(name = "redisson")@ConditionalOnProperty(prefix = "spring.redis", name = "host")public Redisson redissonSingleServer(@Value("${spring.redis.host}") String host, @Value("${spring.redis.port}") String port, @Value("${spring.redis.password}") String password) {Config config = new Config();config.useSingleServer().setAddress("redis://" + host + ":" + port);config.useSingleServer().setPassword(password);return (Redisson) Redisson.create(config);}}

3.3 redis服务器配置

与前面的配置一毛一样。。。。

3.4 Redisson的应用:(一)作为缓存


@Service
public class UserService {@AutowiredRedisson redisson;@Resourceprivate RedissonClient redissonClient;private static final String USER_CACHE = "USER_CACHE";//与Redis、Lettuce相似的功能,这里使用MapCache,还提供了如对列、链表等对象public Object getUser(String username) {if (redissonClient.getMapCache(USER_CACHE).get(username) == null) {System.out.println("未获取到缓存,新建用户信息.............");Map<String, Object> user = new HashMap<>();user.put("username", username);user.put("usercode", "zhangsan");user.put("sex", "男");user.put("createtime", new Date());redissonClient.getMapCache(USER_CACHE).put(username, user);}return redissonClient.getMapCache(USER_CACHE).get(username);}}

代码验证:

 @Testpublic void mapCache() {System.out.println(userService.getUser("11"));System.out.println(userService.getUser("2"));}

输出:
在这里插入图片描述
Redis服务器端存储数据展示,这里由于没有配置序列化,所以键和值都编码过了,不太识别。
在这里插入图片描述

3.5 Redisson应用:(二)分布式锁

测试代码为两个方法:处理用户消息打印。一个加了分布式锁,一个没有加锁的方法,测试时使用多线程模拟分布式效果。

  • 加了分布式锁,即希望所有服务端同一时间仅一人能说话,其他人必须 等待说了“完毕”后,才能说话;
  • 不加分布式锁,不加分布式锁,但同一时间仅一人能说话,实际也应该加锁。但对于分布式来说,单机加不加锁都不影响。为了测试就不加锁。

不用分布式锁:

    public void print(String user, String content) {try {System.out.println(String.format("收到%s的消息", user));System.out.println(String.format("%s说:%s", user, content));Thread.sleep(3000);System.out.println(String.format("%s说完了", user));} catch (Exception ex) {throw new RuntimeException(ex);} finally {}}@Testpublic void print() {new Thread(() -> {userService.print("张三", "你好");}).start();new Thread(() -> {userService.print("李四", "你好");}).start();try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}

输出:
都没有等张三说“完毕”时,李四已经开始说话了。如果是在做秒杀、抢购。那只能快点提桶跑路!
在这里插入图片描述

加了分布式锁的情况:

public void printLock(String user, String content) {RLock lock = null;try {lock = redisson.getLock("printNow");lock.lock();System.out.println(String.format("收到%s的消息", user));System.out.println(String.format("%s说:%s", user, content));for (int i = 0; i < 3; i++) {System.out.println("思考中....");Thread.sleep(1000);}System.out.println("完毕....");} catch (Exception ex) {throw new RuntimeException(ex);} finally {if (lock != null) {lock.unlock();}}}@Testpublic void printLock() {new Thread(() -> {userService.printLock("张三", "你好");}).start();new Thread(() -> {userService.printLock("李四", "你好");}).start();try {Thread.sleep(50000);} catch (InterruptedException e) {e.printStackTrace();}}

输出:加了分布式锁之后,只要没有说完毕,张三就必须一直等待。
在这里插入图片描述

综上,本章内容完毕了。

总结

  • Lettuce是SpringBoot自带的Redis客户端,性能比Redis要好, 是线程安全的,支持同步编程,异步编程,响应式编程,自动重新连接,主从模式,集群模块,哨兵模式
  • Redisson 是一个在 Redis 的功能基础上实现的 Java 驻内存数据网格客户端。实现了分布式和可扩展的 Java 数据结构,提供很多分布式相关操作服务,例如分布式锁,分布式集合,可通过 Redis 支持延迟队列。

1、Lettuce的自动配置

	<!-- redis 缓存操作自动配置  使用 Lettuce 客户端--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- pool 对象池 Lettuce 要依赖这个--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>

代码中使用自动注入即可

@Service
public class UserService {@AutowiredRedisTemplate redisTemplate;//redisTemplate.opsForValue().get("zhangsan")//redisTemplate.opsForValue().set("zhangsan", "李四");
}

2、Redisson的自动配置

引入redisson的自动配置后,我们上面示例中的RedissonConfiguration类也不需要写了,直接用就行。

        <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.3</version></dependency>

代码中直接注入即可:

@Service
public class UserService {@AutowiredRedisson redisson;@Resourceprivate RedissonClient redissonClient;
}

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

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

相关文章

【数据库原理】(9)SQL简介

一.SQL 的发展历史 起源&#xff1a;SQL 起源于 1970 年代&#xff0c;由 IBM 的研究员 Edgar F. Codd 提出的关系模型概念演化而来。初期&#xff1a;Boyce 和 Chamberlin 在 IBM 开发了 SQUARE 语言的原型&#xff0c;后发展成为 SQL。这是为了更好地利用和管理关系数据库。…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)创建并初始化TcpServer实例 以及 启动

对于一个TcpServer来说&#xff0c;它的灵魂是什么&#xff1f;就是需要提供一个事件循环EventLop(EventLoop)&#xff0c;不停地去检测有没有客户端的连接到达&#xff0c;有没有客户端给服务器发送数据&#xff0c;描述的这些动作&#xff0c;反应堆模型能够胜任。当服务器和…

【动态规划】【字符串】132.分割回文串 II

作者推荐 【动态规划】【字符串】扰乱字符串 本文涉及的基础知识点 动态规划 字符串 LeetCode132. 分割回文串 II 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1&#xff1a; 输入&#x…

真核微生物基因序列鉴定工具EukRep工具的安装和详细使用方法

介绍 EukRep是一种用于鉴定并分析环境中的真核微生物的工具。它基于16S rRNA基因序列&#xff0c;可以帮助研究人员确定和分类环境样品中存在的真核微生物群落。 EukRep 从宏基因组数据集中分类真核和原核序列 安装 要求Python3 推荐使用conda安装&#xff1a; $ conda cre…

操作系统期末复习大题---经典进程的同步问题

目录 一、经典进程的同步问题 1. 利用记录型信号量解决生产者—消费者问题 执行流程&#xff1a; ”生产者-消费者”问题模型代码框架如下&#xff1a; 注意&#xff1a; 小结&#xff1a; 复习典型例题&#xff1a; 解答&#xff1a; 2. 利用AND信号量解决生产者——…

【React系列】Hook(二)高级使用

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. Hook高级使用 1.1. useReducer 很多人看到useReducer的第一反应应该是redux的某个替代品&#xff0c;其实并不是…

git rebase(变基)应用场景

文章目录 git rebase(变基)应用场景1.git rebase -i HEAD~3 git rebase(变基)应用场景 使得提交记录变得简洁 现在我们模拟我们有多次提交记录&#xff0c;本地仓库有三条提交 整合成一条提交记录 1.git rebase -i HEAD~3 提交记录合并 HEAD~3合并三条记录 执行之后 然后把…

.NET Standard 支持的 .NET Framework 和 .NET Core

.NET Standard 是针对多个 .NET 实现推出的一套正式的 .NET API 规范。 推出 .NET Standard 的背后动机是要提高 .NET 生态系统中的一致性。 .NET 5 及更高版本采用不同的方法来建立一致性&#xff0c;这种方法在大多数情况下都不需要 .NET Standard。 但如果要在 .NET Framewo…

SAP设置修改删除自动JOB

一、设置JOB 方法一 一个不需要单独记事务码的方式 如果FS要求开发做了程序的话&#xff0c;直接执行事务码&#xff0c;点击左上角 程序-后台执行 输出设备选择LP01 打勾&#xff0c;有可能还有一个对话框&#xff0c;也打勾 打勾后设置周期值 系统预设的会有小时、天、周…

创新性文生视频模型,南洋理工开源FreeInit

文本领域的ChatGPT&#xff0c;画图领域的Midjourney都展现出了大模型强大的一面&#xff0c;虽然视频领域有Gen-2这样的领导者&#xff0c;但现有的视频扩散模型在生成的效果中仍然存在时间一致性不足和不自然的动态效果。 南洋理工大学S实验室的研究人员发现&#xff0c;扩散…

Spring Cloud Gateway + Nacos 灰度发布

前言 本文将会使用 SpringCloud Gateway 网关组件配合 Nacos 实现灰度发布&#xff08;金丝雀发布&#xff09; 环境搭建 创建子模块服务提供者 provider&#xff0c;网关模块 gateway 父项目 pom.xml 配置 <?xml version"1.0" encoding"UTF-8"?…

【Spring实战】22 Spring Actuator 入门

文章目录 1. 定义2. 功能3. 依赖4. 配置5. 常用的应用场景1&#xff09;环境监控2&#xff09;运维管理3&#xff09;性能优化 结论 Spring Actuator 是 Spring 框架的一个模块&#xff0c;为开发人员提供了一套强大的监控和管理功能。本文将深入探讨 Spring Actuator 的定义、…

【HTML5】第1章 HTML5入门

学习目标 了解网页基本概念&#xff0c;能够说出网页的构成以及网页相关名词的含义 熟悉Web标准&#xff0c;能够归纳Web标准的构成。 了解浏览器&#xff0c;能够说出各主流浏览器的特点。 了解HTML5技术&#xff0c;能够知道HTML5发展历程、优势以及浏览器对HTML5的支持情…

【QT】QStandardItemModel类的应用介绍

目录 1 概述 2 常用方法 3 QStandardItemModel的使用 3.1 界面设计与主窗口类定义 3.2 系统初始化 3.3 从文本文件导入数据 3.4 数据修改 3.5 单元格格式设置 3.6 数据另存为文件 1 概述 QStandardItemModel是标准的以项数据&#xff08;itemdata&#xff09;为基础的…

FPGA项目(14)——基于FPGA的数字秒表设计

1.功能设计 设计内容及要求: 1.秒表最大计时范围为99分59. 99秒 2.6位数码管显示&#xff0c;分辨率为0.01秒 3.具有清零、启动计时、暂停及继续计时等功能 4.控制操作按键不超过二个。 2.设计思路 所采用的时钟为50M&#xff0c;先对时钟进行分频&#xff0c;得到100HZ频率…

CSS 放大翻转动画

<template><div class="container" @mouseenter="startAnimation" @mouseleave="stopAnimation"><!-- 旋方块 --><div class="box" :class="{ rotate-scale-up-hor: isAnimating }"><!-- 元素内…

macosx编译qgroundcontrol源码(Qt6.7)

1.克隆源码: clone --recursive http://github.com/mavlink/qgroundcontrol.git 克隆成功 3.编译 编译环境要求: 编译方法: 使用QtCreator编译 使用命令行编译 打开QGroundControl.pro并编译IOS版本 旧版本使用Qt 5.15.2 run qmake 新版本使用Qt 6.6或者更高 IOS工程输出要…

mysql5.7安装-windows安装版本

下载地址 官网地址:https://www.mysql.com/官网下载地址:https://dev.mysql.com/downloads/mysql/阿里云镜像站下载:https://mirrors.aliyun.com/mysql/华为云镜像站地址:https://mirrors.huaweicloud.com/home华为云镜像站下载:https://mirrors.huaweicloud.com/mysql/Downlo…

英飞凌TC3xx之一起认识GTM(九)GTM相关知识简述(CMU,CCM,TBU,MON)

英飞凌TC3xx之一起认识GTM(九)GTM相关知识简述(CMU,CCM,TBU,MON) 1 时钟管理单元(CMU)2 集群配置模块(CCM)3 时基单元(TBU)4 监控单元(MON)5 总结由前文的各篇内容,开发者已经知道如何使用GTM的大部分功能,在这些功能中,都需要一个信息就是fGTM 的数据,我们在前…

技术查漏补缺(1)Logback

一、下定义&#xff1a;Logback是一个开源的日志组件 二、Logback的maven <!--这个依赖直接包含了 logback-core 以及 slf4j-api的依赖--> <dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><v…