抽丝剥茧,Redis使用事件总线EventBus或AOP优化健康检测

目录

前言

Lettuce

什么是事件总线EventBus?

Connected

Connection activated

Disconnected

Connection deactivated

Reconnect failed

使用

一种另类方法—AOP

具体实现


前言

在上一篇深入浅出,SpringBoot整合Quartz实现定时任务与Redis健康检测(二)_往事如烟隔多年的博客-CSDN博客

文章中,通过在SpringBoot中使用Quartz实现了Redis健康状态的检测,虽然一定程度上解决了Redis的连接问题,但仍存在一些问题,比如当Redis在定时检测的间隔时间内断开连接时,此时有用户请求进入时仍然会出现服务不可用的状态,那么有办法能够在Redis断开时通知到SpringBoot程序,进而实现Redis到MySQL的切换呢?本文将在之前的基础上使用Redis的事件总线机制来解决该问题。

Lettuce

在SpringBoot 2.x版本中默认使用的Redis客户端为Lettuce,与早期的Jedis不同,Lettuce底层由Netty构建,异步IO驱动提升效率,支持高并发,且线程安全。由下图可以看出项目中引入了Redis依赖后使用的客户端为Lettuce

什么是事件总线EventBus?

虽然引入了Lettuce,但是面临的问题应该如何作以解决呢?这里就得讲一下Redis的EventBus了,可以通过Lettuce官方文档了解相关信息,

Connection Events · lettuce-io/lettuce-core Wiki · GitHub

由于客户端使用了lettuce6.1.10,因此我们关注内容如下Connection Events · lettuce-io/lettuce-core Wiki · GitHub

不难看出自lettuce提供了一个用于使用连接事件的实例代码,通过订阅事件总线可以监听到当前Redis的连接事件状态,连接事件状态分为如下五种:

Connected

传输协议连接建立,即TCP三次握手完成,Socket通信建立,事件类型ConnectedEvent。

Connection activated

逻辑连接建立,当前处于活动状态并且可以开始分发Redis命令,此时ping命令已经发送并收到回应,可以正常使用Redis命令。事件类型ConnectionActivatedEvent。

Disconnected

连接关闭,传输协议关闭或重置。该事件发生在定期关闭和连接中断时,事件类型Disconnected。

Connection deactivated

连接停用,逻辑连接停用,内部的处理状态被重置,并且isOpen()标志被设置为false,该事件发生在定期关闭和连接中断时,事件类型Connection deactivated。

Reconnect failed

重连失败(自5.3版起),尝试重连失败。包含重连失败和重连计数器。事件类型RecconectFailedEvent。

如上五种类型中需要重点关注的是Connection activated,当该连接事件发生时,将Redis连接标识置为true即可。

使用

根据前文提到的官方文档给出的代码,使用后会发现并未监听到Redis的连接状态。

RedisClient client = RedisClient.create()
EventBus eventBus = client.getresources().eventBus();eventBus.get().subscribe(e -> System.out.println(event));...
client.shutdown();

此时进入create()方法内部查看情况,可以看到默认无参的构造函数创建了一个RedisClient对象,其中第一个参数为clientResources对象,第二个参数为一个字符串,即空的URI,想必在这里已经猜到为什么无法监听连接了。

由于并没有传入对应的Redis资源或URI路径,导致无法进行正常的事件监听。

在源码中不难发现有其它同名含参的构造方法, 此处使用第三个含有ClientResource对象的方法,因为可以通过Spring注入该对象,从而省去手工构造的繁琐步骤。

具体代码如下

通过创建事件总线对象,进而订阅Redis的连接事件,当Reids处于非连接状态时会实时修改RedisCheckConfig的连接状态标识。即使在Redis定时检测任务的间隔中也能保证服务的正常运行。

@Component
@Slf4j
public class RedisStatusListener {@Autowiredprivate ClientResources clientResources;public RedisClient redisClient() {RedisClient client = RedisClient.create(clientResources);EventBus eventBus = client.getResources().eventBus();eventBus.get().subscribe(e -> {RedisCheckConfig.redisConnected = e instanceof ConnectionActivatedEvent ? true : false;log.info("EventBus获取Redis是否连接 "+RedisCheckConfig.redisConnected);});return client;}
}

一种另类方法——AOP

如果并不想使用事件总线的方式来解决,这里再提供一种其它的思路。可以通过AOP的方式来完成判断。

通过对Redis操作类中的所有操作指令进行检测,即当Redis操作命令执行超过1s(可调节)时则认为此时Redis出现了连接异常。

这里由于需要统计执行时间需要用到线程池,通过AOP的环绕通知来实现业务逻辑拦截,即当Redis命令操作超过指定时间则返回数据为其对应存储数据的默认类型。

具体实现

@Component
@Aspect
@Slf4j
public class RedisOperationAspect {@Around("execution(* com.o2o.shop.util.RedisOperator.*(..))")public Object monitorRedisCommandExecution(ProceedingJoinPoint joinPoint) throws Throwable {// 获取方法信息MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();Method method = methodSignature.getMethod();String methodName = method.getName();// 执行超时时间,单位mslong timeout = 1000;ExecutorService executor = new ThreadPoolExecutor(1, 1,1000, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(1));// 创建Future对象Future<Object> future = executor.submit(() -> {try {return joinPoint.proceed();} catch (Throwable throwable) {log.error("Redis AOP 执行 "+joinPoint+"异常");throw new RuntimeException(throwable);}});// 执行方法并等待结果,设置超时时间try {return future.get(timeout, TimeUnit.MILLISECONDS);} catch (TimeoutException e) {// 超时处理log.warn("Redis command execution timed out");// 中断方法执行future.cancel(true);// 返回特定结果Class<?> returnType = method.getReturnType();if (returnType.isPrimitive()) {if (returnType == boolean.class) {return false;} else if (returnType == char.class) {return '\0';} else if (returnType == byte.class || returnType == short.class ||returnType == int.class || returnType == long.class) {return 0;} else if (returnType == float.class || returnType == double.class) {return 0.0f;}}return null;} finally {// 关闭线程池executor.shutdown();}}}

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

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

相关文章

openGauss学习笔记-108 openGauss 数据库管理-管理用户及权限-用户

文章目录 openGauss学习笔记-108 openGauss 数据库管理-管理用户及权限-用户108.1 创建、修改和删除用户108.2 私有用户108.3 永久用户108.4 用户认证优先规则 openGauss学习笔记-108 openGauss 数据库管理-管理用户及权限-用户 使用CREATE USER和ALTER USER可以创建和管理数据…

百度文心一言4.0——使用及API测试

登录百度智能云&#xff1a;百度智能云 文心一言4.0使用 开通付费&#xff1a; 创建应用&#xff1a; 自行创建应用名称&#xff1a; 对话测试&#xff1a; API测试 ERNIE-Bot-4 API&#xff1a;ERNIE-Bot-4 打开链接查看自己的API Key&#xff0c;Secret Key。 可参…

高速下载b站视频的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

JavaWeb——Servlet原理、生命周期、IDEA中实现一个Servlet(全过程)

6、servlet 6.1、什么是servlet 在JavaWeb中&#xff0c;Servlet是基于Java编写的服务器端组件&#xff0c;用于处理客户端&#xff08;通常是Web浏览器&#xff09;发送的HTTP请求并生成相应的HTTP响应。Servlet运行在Web服务器上&#xff0c;与Web容器&#xff08;如Tomcat&…

如何平衡 Wi-Fi 7 与未来 5G/6G 的发展?

随着社会进步&#xff0c;人们对信息技术的需求不断提升。当前互联网、大数据、云计算、人工智能、区块链等新技术深刻演变&#xff0c;产业数字化、智能化、绿色化转型不断加速&#xff0c;智能产业、数字经济蓬勃发展&#xff0c;极大改变全球要素资源配置方式、产业发展模式…

Auth.js:多合一身份验证解决方案 | 开源日报 No.60

nodejs/node Stars: 96.2k License: NOASSERTION Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。它具有以下关键特性和核心优势&#xff1a; 强大&#xff1a;Node.js 提供了强大且高效的服务器端运行能力&#xff0c;可以处理并发请求&#xff0c;并支持异步编程…

深度学习--通过对Keras进行微调提升性能

本文使用微调(Fine-tune)技术来提升模型的性能。前面我们通过迁移学习将这个猫狗大战二分类问题的预测准确率提升到了90%左右,看上去效果已经很不错了,但是还能不能进一步提升了呢? 前面我们没有对VGG16的卷积层进行参数的优化,那么我们这里就可以来优化这部分的参数。由…

京东(天猫)数据分析:2023下半年茶饮料市场高速增长,东方树叶一骑绝尘

当前在食品饮料行业中&#xff0c;整体的增长放缓&#xff0c;且各个细分品类上都已经充分竞争。但茶饮料市场例外&#xff0c;近两年呈现高增长的态势&#xff0c;一来取决于行业头部企业也在积极推动茶饮料不断升级&#xff0c;另外是主打更健康、更时尚的茶饮料深受年轻消费…

分代ZGC详解

ZGC&#xff08;Z Garbage Collector&#xff09;是Java平台上的一种垃圾收集器&#xff0c;它是由Oracle开发的&#xff0c;旨在解决大堆的低延迟垃圾收集问题。ZGC是一种并发的分代垃圾收集器&#xff0c;它主要针对具有大内存需求和低停顿时间要求的应用程序 分代ZGC收集器…

【分布式】: 幂等性和实现方式

【分布式】: 幂等性和实现方式 幂等&#xff08;idempotent、idempotence&#xff09;是一个数学与计算机学概念&#xff0c; 常见于抽象代数中。在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数&#xff0c;或幂等方法&#xff0c;是…

docker搭建waline评论系统

我这里是给博客网站嵌入评论系统的 1.登录LeanCloud 国际版&#xff0c;没有账号可以注册个 链接&#xff1a;点击跳转 2.新建应用&#xff0c;选择开发版&#xff08;免费&#xff09;&#xff0c;商用版每个月最低消费5美刀。 3.在设置-应用凭证里面将AppID、AppKey、Maste…

PHP MySQL 交互 笔记/练习

PHP 与 MySQL 交互 交互函数 函数名作用mysqli_connect()与MySQL 数据库建立连接。mysqli_close()关闭与MYSQL 数据库建立的连接。mysqli_connect_errno()与MySQL 数据库建立连接时&#xff0c;发生错误时的错误编号。mysqli_connect_error()与MySQL 数据库建立连接时&#x…

Spark_SQL-DataFrame数据写出以及读写数据库(以MySQl为例)

一、数据写出 &#xff08;1&#xff09;SparkSQL统一API写出DataFrame数据 统一API写法&#xff1a; 常见源写出&#xff1a; # cording:utf8from pyspark.sql import SparkSession from pyspark.sql.types import StructType, IntegerType, StringType import pyspark.sql.fu…

html 常见兼容性问题

目录 前言: 用法: 代码: 1. 盒模型差异: 2. 表格布局问题: 3. 浏览器前缀问题: 4. 字体渲染问题: 理解: 讨论: 前言: 在Web开发中&#xff0c;兼容性问题是常见的挑战之一。不同的浏览器和设备可能以不同的方式解释和呈现HTML&#xff0c;导致网页在某些环境下出现问题…

LabVIEW在 XY Graph中选择一组点

LabVIEW在 XY Graph中选择一组点 问题&#xff1a;有一个包含许多点的XY Graph&#xff0c;在程序开发中&#xff0c;对于显示XY Graph中的多个点&#xff0c;如何进行选取。最好能像图像处理中的ROI一样&#xff0c;并且它们的颜色可以更改&#xff0c;可以在其中选择一些ROI…

PyTorch基础(18)-- torch.stack()方法

一、方法详解 首先&#xff0c;看一下stack的直观解释&#xff0c;动词可以简单理解为&#xff1a;把……放成一堆、把……放成一摞。 有了对stack方法的直观感受&#xff0c;接下来&#xff0c;我们正式解析torch.stack方法。 PyTorch torch.stack() method joins (concaten…

解决报错:gnutls_handshake() failed: The TLS connection was non-properly terminated.

执行git clone的时候&#xff0c;出现错误&#xff1a;gnutls_handshake() failed: The TLS connection was non-properly terminated. 如图&#xff1a; 解决方式&#xff1a; 两次重置代理&#xff1a;完美解决 git config --global --unset https.https://github.com.pro…

派克斯电脑全局改IP如何辅助捉妖游戏

捉妖游戏是一款非常受欢迎的手机游戏&#xff0c;玩家需要通过探索地图来捉到各种可爱的妖精。为了让游戏更具趣味性&#xff0c;玩家可以通过地图制作来设计自己的捉妖之旅。在这篇教程中&#xff0c;我们将向您展示如何使用电脑全局软件工具——派克斯&#xff0c;来制作捉妖…

优思学院|六西格玛证书怎么考?7个步骤助你马上取得

在当今竞争激烈的职场环境中&#xff0c;持有六西格玛证书可以为您的职业生涯增添亮点。 事实上&#xff0c;六西格玛认证的机构还是挺多&#xff0c;首先&#xff0c;是独立的认证组织授予的认证&#xff0c;例如比如美质协、国际精益六西格玛研究所&#xff08;ILSSI&#x…