解决使用lettuce连接Redis超时的问题(tcpUserTimeout 参数失效问题)

问题背景

lettuce 连接Redis的主从实例,当主节的主机异常下电重启后,由于没有发送RST 包,导致 lettuce 一直在复用之前的TCP链接,然后会出现连接超时的情况。一直出现io.lettuce.core.RedisCommandTimeoutException: Command timed out after 的错误,直到约15分钟后,TCP不再重传,断开连接才恢复
详细原因参考:
https://juejin.cn/post/7494573414150438927#heading-5
https://www.modb.pro/db/1711557186789908480
https://github.com/lettuce-io/lettuce-core/issues/2082
https://support.huaweicloud.com/usermanual-dcs/dcs-ug-211105002.html

解决方案

最简单的是修改客户端操作系统的TCP重传次数,例如改为 8次。就可以不再等待15分钟
sysctl -w net.ipv4.tcp_retries2=8
但是由于影响较大,也会影响主机上其他的TCP连接,此方案被排除。
于是按照官方提供的方案(参考:https://github.com/lettuce-io/lettuce-core/issues/2082https://support.huaweicloud.com/usermanual-dcs/dcs-ug-211105002.html),升级 lettuce 的依赖到 6.3.0,同时设置tcpUserTimeout 参数
升级版本并设置tcpUserTimeout,应用日志显示参数不生效,同时验证后确实无效,问题依然存在
采用如下依赖:

<dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.3.0.RELEASE</version>
</dependency><dependency><groupId>io.netty</groupId><artifactId>netty-transport-native-epoll</artifactId><version>4.1.100.Final</version><classifier>linux-x86_64</classifier>
</dependency>

日志显示:

2025-05-06 13:40:05.024  WARN 1939829 --- [nio-8888-exec-1] io.lettuce.core.ConnectionBuilder        : Cannot apply TCP User Timeout options to channel type io.netty.channel.socket.nio.NioSocketChannel
2025-05-06 13:40:05.390  WARN 1939829 --- [ioEventLoop-6-1] io.lettuce.core.ConnectionBuilder        : Cannot apply TCP User Timeout options to channel type io.netty.channel.socket.nio.NioSocketChannel
2025-05-06 13:40:05.394  WARN 1939829 --- [ioEventLoop-6-1] io.lettuce.core.ConnectionBuilder        : Cannot apply TCP User Timeout options to channel type io.netty.channel.socket.nio.NioSocketChannel
2025-05-06 13:40:05.396  WARN 1939829 --- [ioEventLoop-6-1] io.lettuce.core.ConnectionBuilder        : Cannot apply TCP User Timeout options to channel type io.netty.channel.socket.nio.NioSocketChannel

分析依赖判断是netty的冲突问题于是修改依赖的配置如下:

		<dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.3.0.RELEASE</version></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.100.Final</version></dependency>

应用启动不再提示,并且在故障后30s出现重连的日志,说明tcpUserTimeout参数生效了。

2025-05-07 09:07:59.411  INFO 2112812 --- [xecutorLoop-1-6] i.l.core.protocol.ConnectionWatchdog     : Reconnecting, last destination was 10.50.190.43:6379
2025-05-07 09:07:59.419  INFO 2112812 --- [llEventLoop-6-3] i.l.core.protocol.ReconnectionHandler    : Reconnected to 10.50.190.43:6379

Redis配置类如下:

@Configuration
public class RedisConfig {@Value("${spring.redis.host}")private String redisHost;@Value("${spring.redis.port:6379}")private Integer redisPort = 6379;@Value("${spring.redis.database:0}")private Integer redisDatabase = 0;@Value("${spring.redis.password:}")private String redisPassword;@Value("${spring.redis.connect.timeout:2000}")private Integer redisConnectTimeout = 2000;@Value("${spring.redis.read.timeout:2000}")private Integer redisReadTimeout = 2000;/*** TCP_KEEPALIVE 配置参数:* 两次 keepalive 间的时间间隔 = TCP_KEEPALIVE_TIME = 30* 连接空闲多久开始 keepalive = TCP_KEEPALIVE_TIME/3 = 10* keepalive 几次之后断开连接 = TCP_KEEPALIVE_COUNT = 3*/private static final int TCP_KEEPALIVE_TIME = 30;/*** TCP_USER_TIMEOUT 连接空闲限制时间,解决Lettuce长时间超时问题。* refer: https://github.com/lettuce-io/lettuce-core/issues/2082*/private static final int TCP_USER_TIMEOUT = 30;@Beanpublic LettuceConnectionFactory redisConnectionFactory(LettuceClientConfiguration clientConfiguration) {RedisStandaloneConfiguration standaloneConfiguration = new RedisStandaloneConfiguration();standaloneConfiguration.setHostName(redisHost);standaloneConfiguration.setPort(redisPort);standaloneConfiguration.setDatabase(redisDatabase);standaloneConfiguration.setPassword(redisPassword);LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(standaloneConfiguration, clientConfiguration);connectionFactory.setDatabase(redisDatabase);return connectionFactory;}@Beanpublic LettuceClientConfiguration clientConfiguration() {SocketOptions socketOptions = SocketOptions.builder().keepAlive(SocketOptions.KeepAliveOptions.builder()// 两次 keepalive 间的时间间隔.idle(Duration.ofSeconds(TCP_KEEPALIVE_TIME))// 连接空闲多久开始 keepalive.interval(Duration.ofSeconds(TCP_KEEPALIVE_TIME / 3))// keepalive 几次之后断开连接.count(3)// 是否开启保活连接.enable().build()).tcpUserTimeout(SocketOptions.TcpUserTimeoutOptions.builder()// 解决服务端rst导致的长时间超时问题.tcpUserTimeout(Duration.ofSeconds(TCP_USER_TIMEOUT)).enable().build())// tcp 连接超时设置.connectTimeout(Duration.ofMillis(redisConnectTimeout)).build();ClientOptions clientOptions = ClientOptions.builder().autoReconnect(true).pingBeforeActivateConnection(true).cancelCommandsOnReconnectFailure(false).disconnectedBehavior(ClientOptions.DisconnectedBehavior.ACCEPT_COMMANDS).socketOptions(socketOptions).build();LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder().commandTimeout(Duration.ofMillis(redisReadTimeout)).readFrom(ReadFrom.MASTER).clientOptions(clientOptions).build();return clientConfiguration;}@BeanRedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);System.out.println("SocketOptions: " + redisConnectionFactory.getClientConfiguration().getClientOptions().get().getSocketOptions().getTcpUserTimeout().getTcpUserTimeout().toString());return template;}}

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

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

相关文章

如何使用python保存字典

在Python中&#xff0c;可以通过多种方式将字典&#xff08;dict&#xff09;保存到文件中&#xff0c;并能够随时读取恢复。以下是几种常见的方法&#xff1a; 1. 使用 json 模块&#xff08;推荐&#xff09; 适用场景&#xff1a;需要人类可读的文件格式&#xff0c;且数据不…

SQL 与 Python:日期维度表创建的不同选择

文章目录 一、日期维度表概述日期维度表结构 二、使用 SQL 创建日期维度表2.1 表结构设计2.2 数据插入2.3 SQL 创建方式的优势与局限 三、使用 Python 创建日期维度表3.1 依赖库引入3.2 代码实现3.3 Python 创建方式的优势与局限 四、应用场景与选择建议4.1 应用场景4.2 选择建…

如何用postman进行批量操作

业务场景&#xff1a; 有些时候&#xff0c;我们会需要批量的将SAP B1系统中的几千条的数据删除或者取消单据&#xff0c;这个时候&#xff0c;一条条去操作&#xff0c;指定是到猴年马月了。SAP Business One本身提供了DTW这个工具&#xff0c;但是这个更新&#xff0c;可以操…

Mysql如何完成数据的增删改查(详解从0到1)

前言&#xff1a; Mysql可能是每个程序员的必修课&#xff0c;可以说是使用起来是没有什么问题的&#xff0c;但是作为一名合格的程序猿&#xff0c;深入学习Mysql的内部工作原理是非常有必要的&#xff0c;主要是理解和学习Mysql的底层思想&#xff0c;希望在日后如遇到一些&…

单片机嵌入式按键库

kw_btn库说明 本库主要满足嵌入式按键需求&#xff0c;集成了常用的按键响应事件&#xff1a;高电平、低电平、上升沿、下降沿、单击、双击、长按键事件。可以裸机运行&#xff0c;也可以配合实时操作系统运行。 本库开源连接地址&#xff1a;连接 实现思路 本库采用C语言进行…

Qt—鼠标移动事件的趣味小程序:会移动的按钮

1.项目目标 本次根据Qt的鼠标移动事件实现一个趣味小程序&#xff1a;当鼠标移动到按钮时&#xff0c;按钮就会随机出现在置&#xff0c;以至于根本点击不到按钮。​​​​​ 2.项目步骤 首先现在ui界面设计控件(也可以用代码的方式创建&#xff0c;就不多说了) 第一个按钮不需…

MySQL的information_schema在SQL注入中的关键作用与防御策略

目录 一、information_schema的核心价值 二、攻击利用场景与示例 1. 联合查询注入&#xff08;Union-Based&#xff09; 2. 报错注入&#xff08;Error-Based&#xff09; 3. 布尔盲注&#xff08;Boolean Blind&#xff09; 4. 时间盲注&#xff08;Time-Based&#xff0…

c语言 关键字--目录

下面是详细介绍的链接 1.c语言 关键字 2.typedef 关键字 3.volatile 关键字 4.register 关键字 5.const关键字用法 6.extern关键字 7.sizeof关键字

python爬虫爬取网站图片出现403解决方法【仅供学习使用】

基于CSDN第一篇文章&#xff0c;Python爬虫之入门保姆级教程&#xff0c;学不会我去你家刷厕所。 这篇文章是2021年作者发表的&#xff0c;由于此教程&#xff0c;网站添加了反爬机制&#xff0c;有作者通过添加cookie信息来达到原来的效果&#xff0c;Python爬虫添加Cookies以…

docker创建一个centOS容器安装软件(以宝塔为例)的详细步骤

备忘&#xff1a;后续偶尔忘记了docker虚拟机与宿主机的端口映射关系&#xff0c;来这里查看即可&#xff1a; docker run -d \ --name baota \ --privilegedtrue \ -p 8888:8888 \ -p 8880:80 \ -p 8443:443 \ -p 8820:20 \ -p 8821:21 \ -v /home/www:/www/wwwroot \ centos…

linux 使用nginx部署ssl证书,将http升级为https

前言 本文基于&#xff1a;操作系统 CentOS Stream 8 使用工具&#xff1a;Xshell 8、Xftp 8 服务器基础环境&#xff1a; nginx - 请查看 linux 使用nginx部署vue、react项目 所需服务器基础环境&#xff0c;请根据提示进行下载、安装。 1.下载证书 以腾讯云为例&#x…

日常开发中,iOS 性能调优我们怎么做?

日常开发中&#xff0c;iOS 性能调优我们怎么做&#xff1f;聊聊我用过的几款工具 最近在给一个 iOS 视频类 App 做性能优化&#xff0c;过程中踩了不少坑&#xff0c;也用了一些不错的工具&#xff0c;今天就以一个开发者视角随便聊聊我在调试过程中的一些经验。 一、性能问…

Redis ⑨-Jedis | Spring Redis

Jedis 通过 Jedis 可以连接 Redis 服务器。 通过 Maven 引入 Jedis 依赖。 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><versi…

【人工智能】解锁AI潜能:LM Studio多模型并行运行DeepSeek与开源大模型的实践指南

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着大语言模型(LLM)的快速发展,LM Studio作为一款本地化部署工具,以其简单易用的图形化界面和强大的模型管理能力受到广泛关注。本文深…

Node.js面试题

一、什么是Node.js&#xff1f; Node.js 是一个开源的跨平台 JavaScript 运行时环境&#xff0c;允许开发者在服务器端运行 JavaScript 代码。它基于 Chrome 的 V8 JavaScript 引擎构建&#xff0c;能够高效地处理 I/O 操作&#xff0c;适合构建高性能的网络应用。 异步非阻塞&…

Playwright MCP 入门实战:自动化测试与 Copilot 集成指南

什么是 MCP&#xff1f; MCP&#xff08;Model Context Protocol&#xff09; 是一种为大语言模型&#xff08;LLM&#xff09;设计的协议&#xff0c;MCP充当 LLM 与实际应用之间的桥梁或“翻译器”&#xff0c;将自然语言转化为结构化指令&#xff0c;使得模型可以更精确、高…

达梦DM数据库安装步骤

文章目录 1、下载并解压缩2、安装DM数据库2.1 运行安装程序2.2 选择语言与时区2.3 安装向导2.4 许可证协议2.5 Key文件2.6 选择组件2.7 安装位置2.8 安装前小结2.9 安装过程2.10 已完成2.11 初始化 3、配置实例3.1选择操作方式3.2创建数据库模版3.3指定数据库目录3.4数据库标识…

电商双11美妆数据分析(2)

接下来用seaborn包给出每个店铺各个大类以及各个小类的销量销售额 关于性别 接下来考虑性别因素&#xff0c;了解各类产品在男性消费者中的销量占比 男士的销量基本来自于清洁类&#xff0c;其次是补水类。而这两类正是总销量中占比最高的两类。 非男士专用中&#xff0c;补水…

54.实现Trie(前缀树)

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&#xff0c;例如自动补全和拼写检查。 请你实现 Trie 类&#xff1a; Trie() 初始化前缀树对象。void insert(String wo…

Excel文件批量处理指南 | 用VBA一键操作文件夹所有工作簿

系列文章 Excel跨文件夹批处理黑科技 | 用VBA递归遍历所有子目录 目录 系列文章&#x1f4c1; Excel文件批量处理指南 | 用VBA一键操作文件夹所有工作簿一、场景痛点与解决方案二、核心代码架构解析1. 文件遍历引擎2. 安全打开机制3. 错误处理框架 三、7大实战应用场景场景1&a…