抽丝剥茧,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 {

    @Autowired
    private 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();

        // 执行超时时间,单位ms
        long 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();
        }
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用GoQuery实现头条新闻采集

概述 在本文中&#xff0c;我们将介绍如何使用Go语言和GoQuery库实现一个简单的爬虫程序&#xff0c;用于抓取头条新闻的网页内容。我们还将使用爬虫代理服务&#xff0c;提高爬虫程序的性能和安全性。我们将使用多线程技术&#xff0c;提高采集效率。最后&#xff0c;我们将展…

高等数学教材重难点题型总结(五)定积分

总的来说&#xff0c;只要不定积分掌握得好&#xff0c;基础的定积分肯定没问题&#xff1b;对于考研的话&#xff0c;在定积分定义、牛莱公式、反常积分、审敛法的理解要求更高一些&#xff08;数一还会涉及到伽马函数~&#xff09; 1.利用定义计算定积分 2.定积分的近似计算 …

前端使用 printJS 插件打印多页:第一页空白问题解决

printJS({printable: [data:image/jpg;base64,${this.printData.url}],type: image,style: media print { page {size: auto; margin: 0; } body{margin:0 5px}} // 解决出现多页打印时第一页空白问题 })

Kafka - 深入了解Kafka基础架构:Kafka的基本概念

文章目录 Kafka的基本概念 Kafka的基本概念 我们首先了解一些Kafka的基本概念。 1&#xff09;Producer &#xff1a;消息生产者&#xff0c;就是向kafka broker发消息的客户端2&#xff09;Consumer &#xff1a;消息消费者&#xff0c;向kafka broker获取消息的客户端3&…

linux性能分析(五)如何学习linux性能优化

一 如何学习linux性能优化 强调&#xff1a; 由于知识记忆曲线以及某些知识点不常用,所以一定要注重复习思考&#xff1a; 如何进行能力转义以及能力嫁接? --> 真正站在巨人的肩膀上性能调优的目的&#xff1a; 不影响系统稳定性的资源最大利用化补充&#xff1a; 性能…

数据清洗与规范化详解

数据处理流程&#xff0c;也称数据处理管道&#xff0c;是将原始数据转化为有意义的信息和知识的一系列操作步骤。它包括数据采集、清洗、转换、分析和可视化等环节&#xff0c;旨在提供有用的见解和决策支持。在数据可视化中数据处理是可视化展示前非常重要的一步&#xff0c;…

【MATLAB源码-第56期】基于WOA白鲸优化算法和PSO粒子群优化算法的三维路径规划对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1.粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;简称PSO&#xff09;是一种模拟鸟群觅食行为的启发式优化方法。以下是其详细描述&#xff1a; 基本思想&#xff1a; 鸟群在寻找食物时&#xff0c;每只鸟都…

【Solidity】智能合约案例——③版权保护合约

目录 一、合约源码分析&#xff1a; 二、合约整体流程&#xff1a; 1.部署合约&#xff1a; 2.添加实体&#xff1a; 3.查询实体 4.审核版权&#xff1a; 5.版权转让 一、合约源码分析&#xff1a; Copyright.sol&#xff1a;主合约&#xff0c;定义了版权局的实体&#xff…

2023 10月最新Vmd 下载安装教程,WindowsLinux

文章目录 下载Vmdwindows版本安装LINUX版本安装 下载Vmd 谷歌搜索VMD 点击左下角download VMD 可选择对应版本 注&#xff1a;点击后会出现输入用户名和密码&#xff0c;由于我已注册&#xff0c;界面不见了&#xff0c;所以直接描述一下。 输入用户名和密码然后会出现让登记…

力扣刷题 day56:10-26

1.解码异或后的数组 未知 整数数组 arr 由 n 个非负整数组成。 经编码后变为长度为 n - 1 的另一个整数数组 encoded &#xff0c;其中 encoded[i] arr[i] XOR arr[i 1] 。例如&#xff0c;arr [1,0,2,1] 经编码后得到 encoded [1,2,3] 。 给你编码后的数组 encoded 和原…

腾讯云学生专享云服务器介绍及购买攻略

随着互联网技术的不断发展&#xff0c;越来越多的人开始关注云计算领域。作为国内领先的云计算服务商&#xff0c;腾讯云推出了“云校园”扶持计划&#xff0c;完成学生认证即可购买学生专享云服务器。 一、活动对象 仅限腾讯云官网通过个人认证的35岁以下学生用户参与&#x…

微信小程序云开发笔记-初始化商城小程序

缘起&#xff1a;由于痴迷机器人&#xff0c;店都快倒闭了&#xff0c;没办法&#xff0c;拿出点精力给店里搞个小程序&#xff0c;要多卖货才能活下来搞机器人&#xff0c;在此记录一下搞小程序的过程&#xff0c;要不然搞完又忘了。腾讯的云开发&#xff0c;前端和后端都有了…

二、可行性分析与需求分析

文章目录 概念考点练习题一、可行性分析与需求分析1.可行性分析的任务2.可行性研究3.甘特图4.数据流图5.数据字典数据字典的内容 6.需求分析7. 实体联系ER图8. 状态转换图 二、练习题 概念考点练习题 一、可行性分析与需求分析 1.可行性分析的任务 用最小的代价在尽可能短的时…

双非本两年经验,靠这套Java面试题拿下拿下阿里、百度、美团、滴滴、快手、拼多多等大厂offer

背景 博主是双非大学毕业&#xff0c;有两年的互联网经验 社招面试也是一样的流程&#xff1a;项目 八股 算法 项目&#xff1a; 公司项目&#xff0c;涉及的技术包括但不限&#xff1a; 管理域&#xff1a;DDD、CQRS、事件总线、命令总线 运行域&#xff1a;微内核、规则…

Centos磁盘爆满_openEuler系统磁盘爆满清理方法---Linux工作笔记060

磁盘爆满,监控部门就会报警,报警就要处理,但是程序员并不擅长做运维的工作,记录一下把...以后用到会方便: 使用df -h命令可以看到,对应的磁盘占用情况,这里我的/dev/mapper/openeuler-root这个目录 占用的磁盘比较多,到了百分之95了.. 往往就是这个跟目录,我这里/data目录是自…

FoLR:Focus on Local Regions for Query-based Object Detection论文学习笔记

论文地址&#xff1a;https://arxiv.org/abs/2310.06470 自从DETR问询式检测器首次亮相以来&#xff0c;基于查询的方法在目标检测中引起了广泛关注。然而&#xff0c;这些方法面临着收敛速度慢和性能亚优等挑战。值得注意的是&#xff0c;在目标检测中&#xff0c;自注意力机制…

长连接的原理

Apollo的长连接实现是 Spring的DeferredResult来实现的,先看怎么用 import ...RestController RequestMapping("deferredResult") public class DeferredResultController {private Map<String, Consumer<DeferredResultResponse>> taskMap new HashMa…

express session JWT JSON Web Token

了解 Session 认证的局限性 Session 认证机制需要配合 cookie 才能实现。由于 Cookie 默认不支持跨域访问&#xff0c;所以&#xff0c;当涉及到前端跨域请求后端接口的时候&#xff0c;需要做很多额外的配置&#xff0c;才能实现跨域 Session 认证。 注意&#xff1a; 当前端…

深眸科技以需求定制AI视觉解决方案,全面赋能产品外观缺陷检测

产品外观是影响产品质量最重要的因素之一&#xff0c;其平整度、有无瑕疵等不仅影响到产品美观&#xff0c;甚至能够直接影响产品本身的使用和后续加工&#xff0c;给企业带来重大经济损失。 随着人工智能技术的快速发展&#xff0c;机器视觉与AI技术的结合应用加速渗透进工业…

C# 使用base64编码用于加密和解密

base64编码原理&#xff1a;Base64编码是一种将二进制数据转换为ASCII字符的编码方式。它使用64个字符来表示二进制数据&#xff0c;包括大小写字母、数字和两个符号。将3个字节的二进制数据转换为4个字符的文本数据&#xff0c;如果不足3个字节&#xff0c;则在末尾补0&#x…