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

redis相关异常之RedisConnectionExceptionRedisCommandTimeoutException

本文只是分析Letture类型的Redis 池化连接出现的连接超时异常、读超时异常问题。

1.RedisConnectionException

默认是10秒。
通过如下可以配置:

public class MyLettuceClientConfigurationBuilderCustomizer implements LettuceClientConfigurationBuilderCustomizer {@Overridepublic void customize(LettuceClientConfiguration.LettuceClientConfigurationBuilder clientConfigurationBuilder) {
//        spring.redis.timeout等价clientConfigurationBuilder.commandTimeout(Duration.ofSeconds(100));
//        控制连接超时时间,默认是10秒ClientOptions.Builder builder = ClientOptions.builder().socketOptions(SocketOptions.builder().connectTimeout(Duration.ofMillis(10)).build());clientConfigurationBuilder.clientOptions(builder.build());}
}

2.RedisCommandTimeoutException

结论:抛出RedisCommandTimeoutException异常并非数据的写一定失败。只不过Redis内部超时逻辑跟写逻辑是异步处理,所以存在写成功后仍然抛出异常的情况。但是只要出现该异常必须得处理。

io.lettuce.core.RedisCommandTimeoutException: Command timed out after 2 second(s)

2.1.CommandHandler限制

CommandHandler是Netty中的handler。只不过其同时充当入栈、出栈handler。通俗点讲是Redis Write & Flush 数据到通道NioSocketChannel的必经之路。

AsyncCommand存在两大核心功能。其一是包裹用户数据,其二是实现了CompletableFuture接口,方便实现异步相关操作。

public class CommandHandler extends ChannelDuplexHandler implements HasQueuedCommands {private void writeSingleCommand(ChannelHandlerContext ctx, RedisCommand<?, ?, ?> command, ChannelPromise promise){if (!isWriteable(command)) {// 此处的就是判断是否存在超时的核心之处,借用CompletableFuture异步操作功能promise.trySuccess();// 此时说明数据写过程中超过用户设定的超时时间return;}...ctx.write(command, promise);// 数据正常写入,最终归宿是服务端}private static boolean isWriteable(RedisCommand<?, ?, ?> command) {return !command.isDone();}
}
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {public boolean isDone() {return result != null;}
}

通过上述得知,只要CompletableFuture内部的变量result不为空,则就会按TimeoutException处理。所以result值何时赋值呢?

如下所示,CommandHandler处理完数据之后会通过如下方式设置result的值。

public class AsyncCommand<K, V, T> extends CompletableFuture<T> implements RedisCommand<K, V, T>, RedisFuture<T>,CompleteableCommand<T>, DecoratedCommand<K, V, T> {protected void completeResult() {if (command.getOutput() == null) {complete(null);} else if (command.getOutput().hasError()) {doCompleteExceptionally(ExceptionFactory.createExecutionException(command.getOutput().getError()));} else {// 成功发送则Output为字符串类型的“ok”complete(command.getOutput().get());}}
}

3.超时处理时机

3.1.阻塞等待超时

class FutureSyncInvocationHandler extends AbstractInvocationHandler {protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {try {Method targetMethod = this.translator.get(method);// CommandExpiryWriter#writerObject result = targetMethod.invoke(asyncApi, args);if (result instanceof RedisFuture<?>) {...long timeout = getTimeoutNs(command);//用户自定义的超时时间//command:AsyncCommand 利用CompletableFuture异步特性return LettuceFutures.awaitOrCancel(command, timeout, TimeUnit.NANOSECONDS);}return result;} catch (InvocationTargetException e) {throw e.getTargetException();}}
}
public class LettuceFutures {public static <T> T awaitOrCancel(RedisFuture<T> cmd, long timeout, TimeUnit unit) {try {//阻塞 其实内存调用的CompletableFuture#get阻塞方法。如果返回TimeoutExeception则说明AsyncCommand没有执行完毕,超时处理if (!cmd.await(timeout, unit)) {cmd.cancel(true);throw ExceptionFactory.createTimeoutException(Duration.ofNanos(unit.toNanos(timeout)));}return cmd.get();//这个方法还是调用CompletableFuture#get阻塞方法,但是该方法是根据内部属性result进行判断} catch (RuntimeException e) {throw e;} catch (ExecutionException e) {if (e.getCause() instanceof RedisCommandExecutionException) {throw ExceptionFactory.createExecutionException(e.getCause().getMessage(), e.getCause());}if (e.getCause() instanceof RedisCommandTimeoutException) {throw new RedisCommandTimeoutException(e.getCause());}throw new RedisException(e.getCause());} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new RedisCommandInterruptedException(e);} catch (Exception e) {throw ExceptionFactory.createExecutionException(null, e);}}
}

如下伪代码所示:如果result不为null,则根据result类型抛出相关异常。否则通过timedGet在规定时间内阻塞等待,超时则抛出TimeoutException。

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {public T get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException {Object r;long nanos = unit.toNanos(timeout);return reportGet((r = result) == null ? timedGet(nanos) : r);}
}

3.2.定时任务超时处理

public class CommandExpiryWriter implements RedisChannelWriter {public <K, V, T> RedisCommand<K, V, T> write(RedisCommand<K, V, T> command) {potentiallyExpire(command, getExecutorService());//开启定时任务return writer.write(command);//DefaultEndPoint#write}private void potentiallyExpire(RedisCommand<?, ?, ?> command, ScheduledExecutorService executors) {long timeout = applyConnectionTimeout ? this.timeout : source.getTimeout(command);//用户自定义的超时时间if (timeout <= 0) {return;}// 从 timeout 时间之后开始执行定时任务。此时result值如果存在值则说明超时ScheduledFuture<?> schedule = executors.schedule(() -> {if (!command.isDone()) {command.completeExceptionally(ExceptionFactory.createTimeoutException(Duration.ofNanos(timeUnit.toNanos(timeout))));}}, timeout, timeUnit);if (command instanceof CompleteableCommand) {((CompleteableCommand) command).onComplete((o, o2) -> {if (!schedule.isDone()) {schedule.cancel(false);}});}}
}

重点:定时任务判断成功与否的唯一条件就是result是否存在值。情况1,如果此时result = ok表明数据已经在服务端落盘成功,但是同样会抛出RedisCommandTimeoutException。情况2,发送之前出现异常则result值为Throwable类型的异常值。

相关文章:

redis相关异常之RedisConnectionExceptionRedisCommandTimeoutException

本文只是分析Letture类型的Redis 池化连接出现的连接超时异常、读超时异常问题。 1.RedisConnectionException 默认是10秒。 通过如下可以配置&#xff1a; public class MyLettuceClientConfigurationBuilderCustomizer implements LettuceClientConfigurationBuilderCusto…...

Merge the squares! 2023牛客暑期多校训练营4-H

登录—专业IT笔试面试备考平台_牛客网 题目大意&#xff1a;有n*n个边长为1的小正方形摆放在边长为n的大正方形中&#xff0c;每次可以选择不超过50个正方形&#xff0c;将其合并为一个更大的正方形&#xff0c;求一种可行的操作使所有小正方形都被合并成一个n*n的大正方形 1…...

STM32 串口学习(二)

要用跳线帽将PA9与RXD相连&#xff0c;PA10与TXD相连。 软件设计 void uart_init(u32 baud) {//UART 初始化设置UART1_Handler.InstanceUSART1; //USART1UART1_Handler.Init.BaudRatebound; //波特率UART1_Handler.Init.WordLengthUART_WORDLENGTH_8B; //字长为 8 位数据格式U…...

点大商城V2_2.5.0 全开源版 商家自营+多商户入驻 百度+支付宝+QQ+头条+小程序端+unipp开源前端安装测试教程

安装测试环境&#xff1a;Nginx 1.20PHP7.2MySQL 5.6 修复了无法上传开放平台问题 安装说明&#xff1a; 1、上传后端目录至网站 2、导入提供的数据库文件 3、修改数据库配置文件根目录下config.php&#xff0c;增加数据库用户名和密码 4、网站后台直接访问网址&#xff…...

“深入理解SpringBoot:从入门到精通“

标题&#xff1a;深入理解Spring Boot&#xff1a;从入门到精通 摘要&#xff1a;本文将介绍Spring Boot的基本概念和核心特性&#xff0c;并通过示例代码演示如何使用Spring Boot构建一个简单的Web应用程序。 1. 简介 Spring Boot是一个开源的Java框架&#xff0c;旨在简化基…...

PCB绘制时踩的坑 - SOT-223封装

SOT-223封装并不是同一的&#xff0c;细分的话可以分为两种常用的封装。尤其是tab脚的属性很容易搞错。如果你想着用tab脚连接有属性的铺铜&#xff0c;来提高散热效率&#xff0c;那么你一定要注意你购买的器件tab脚的属性。 第一种如下图&#xff0c;第1脚为GND&#xff0c;第…...

Go语法入门 + 项目实战

&#x1f442; Take me Hand Acoustic - Ccile Corbel - 单曲 - 网易云音乐 第3个小项目有问题&#xff0c;不能在Windows下跑&#xff0c;懒得去搜Linux上怎么跑了&#xff0c;已经落下进度了.... 目录 &#x1f633;前言 &#x1f349;Go两小时 &#x1f511;小项目实战 …...

QT控件通过qss设置子控件的对齐方式、大小自适应等

一些复杂控件&#xff0c;是有子控件的&#xff0c;每个子控件&#xff0c;都可以通过qss的双冒号选择器来选中&#xff0c;进行独特的样式定义。很多控件都有子控件&#xff0c;太多了&#xff0c;后面单独写一篇文章来介绍各个控件的子控件。这里就随便来几个例子 例如下拉列…...

基于java在线收银系统设计与实现

摘要 科技的力量总是在关键的地方改变着人们的生活&#xff0c;不仅如此&#xff0c;我们的生活也是离不开这样或者那样的科技改变&#xff0c;有的消费者没有时间去商场购物&#xff0c;那么电商和快递的结合让端口到消费者的距离不再遥远&#xff1b;有的房客因地域或者工作的…...

Linux--进程的新建状态

新建状态&#xff1a; 操作系统创建了进程的内核数据结构&#xff08;task_struct、mm_struct、页表&#xff09;&#xff0c;但是页表没有创建映射关系&#xff0c;而且磁盘里的程序的代码和数据未加载到物理内存...

区间dp,合并石子模板题

设有 N 堆石子排成一排&#xff0c;其编号为 1,2,3,…,N。 每堆石子有一定的质量&#xff0c;可以用一个整数来描述&#xff0c;现在要将这 N 堆石子合并成为一堆。 每次只能合并相邻的两堆&#xff0c;合并的代价为这两堆石子的质量之和&#xff0c;合并后与这两堆石子相邻的…...

C++代码格式化工具clang-format详细介绍

文章目录 clang-format思考代码风格指南生成您的配置运行 clang-format禁用一段代码的格式设置clang-format的设置预览 clang-format 我曾在许多编程团队工作过&#xff0c;这些团队名义上都有“编程风格指南”。该指南经常被写下来并放置在开发人员很少查看的地方。几乎在每种…...

CentOS 7安装PostgreSQL 15版本数据库

目录 一、何为PostgreSQL&#xff1f; 二、PostgreSQL安装 2.1安装依赖 2.2 执行安装 2.3 数据库初始化 2.4 配置环境变量 2.5 创建数据库 2.6 配置远程 2.7 测试远程 三、常用命令 四、用户创建和数据库权限 一、何为PostgreSQL&#xff1f; PostgreSQL是以加州大学…...

QGraphicsView实现简易地图2『瓦片经纬度』

前文链接&#xff1a;QGraphicsView实现简易地图1『加载离线瓦片地图』 地图采用GCJ02 Web 墨卡托投影&#xff0c;最小坐标&#xff1a;(-180.00000000000000,-85.05112877980655)&#xff0c;最大坐标&#xff1a;(180.00000000000000,85.05112877980655)。瓦片地图单张图片像…...

医学图像重建—第一章笔记

序言 本书涵盖内容&#xff1a; 2D parallel beam imaging 2D fan beam imaging 3D parallel ray imaging 3D parallel plane imaging 3D cone beam imaging 算法包括&#xff1a;analytical method&#xff0c;iterative method 应用于&#xff1a; X-ray CT single photon…...

python-pytorch基础之神经网络分类

这里写目录标题 生成数据函数定义数据集定义loader加载数据定义神经网络模型测试输出是否为2个输入数据&#xff0c;输出结果 训练模型函数计算正确率 训练数据并保存模型测试模型准备数据加载模型预测对比结果 生成数据函数 import randomdef get_rectangle():widthrandom.ra…...

【C++ 程序设计】实战:C++ 变量实践练习题

目录 01. 变量&#xff1a;定义 02. 变量&#xff1a;初始化 03. 变量&#xff1a;参数传递 04. 变量&#xff1a;格式说明符 ① 占位符 “%d” 改为格式说明符 “%llu” ② 占位符 “%d” 改为格式说明符 “%f” 或 “%e” 05. 变量&#xff1a;字节数统计 06. 变量&a…...

微软对Visual Studio 17.7 Preview 4进行版本更新,新插件管理器亮相

近期微软发布了Visual Studio 17.7 Preview 4版本&#xff0c;而在这个版本当中&#xff0c;全新设计的扩展插件管理器将亮相&#xff0c;并且可以让用户可更简单地安装和管理扩展插件。 据了解&#xff0c;目前用户可以从 Visual Studio Marketplace 下载各式各样的 VS 扩展插…...

Kafka 入门到起飞 - Kafka怎么做到保障消息不会重复消费的? 消费者组是什么?

Kafka怎么做到避免消息重复消费的&#xff1f; 消费者组是什么&#xff1f; 消费者&#xff1a; 1、订阅Topic&#xff08;主题&#xff09; 2、从订阅的Topic消费&#xff08;pull&#xff09;消息&#xff0c; 3、将消费消息的offset&#xff08;偏移量&#xff09;保存在K…...

MongoDB 的增、查、改、删

Monogo使用 增 单条增加 db.member.insertOne({"name":"张三","age":18,"create":new Date()}) db.member.insert({"name":"李四1","age":18,"create":new Date()}) db.member.insertOne(…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...