1. 背景

新上线了一个服务,在压测的时候大量返回错误,查看报错是io.lettuce.core.RedisCommandTimeoutException: Command timed out after 1 minute(s)

  1. 在系统长时间无请求之后会必现
  2. 出现之后在十几分钟内不会自动重连

对于刚上线的系统,是很有可能出现上述情况的,例如灰度期间,凌晨无人访问的时候会出现,而且会严重影响线上服务

2. 分析

通过现象可以看出,我们的应用应该是拿一个已经断开的Redis连接,所以一直会超时,而且Lettuce也没有去自动重连

3. 调研

通过网上查询,发现这个是个普遍的现象,并提供了解决方法:

  1. 使用Jedis替换Lettuce
  2. 写定时任务不断请求Redis

使用Jedis算作是绕开了这个问题,写定时任务一是增加应用代码,二是会增加了Redis的请求

那么SpringBoot默认指定的Redis连接池Lettuce为什么会有这种问题呢?

3.1 官方Github

3.1.1 FAQ

Lettuce Github FAQ中发现了这个问题,官方提出几个可能的原因:

  1. Redis服务崩了或者网络问题,并且在指定时间未恢复
  2. 命令没有在超时时间内完成
  3. 配置的超时时间和Redis性能不匹配
  4. 阻塞了EventLoop, 例如在RedisFuture的回调方法中
  5. 手动控制setAutoFlushCommands(true/false),但没有flushCommands()

说实话,官方这个回答和我们碰见的问题是完全不沾边,没有请求更别说性能问题了

3.1.2 Issues

看到一个阿里员工提的issue,指出了可能发生这种问题的原因

Lettuce connects to a Redis host and reads and writes normally. However, if the host fails (the hardware problem directly causes the shutdown, and there is no RST reply to the client at this time), the client will continue to time out until the tcp retransmission ends, and it can be recovered. At this time, it takes about 925.6 s in Linux ( Refer to tcp_retries2 ).

指出因为硬件原因,未返回RST到Lettuce客户端,就会导致客户端在925.6秒(根据tcp_retries2)之内使用一个断开的连接,和我们的情况完全一致

会在下述情况出现:

  1. 硬件问题或断电导致的Redis Server宕机
  2. SLB负载均衡,后端地址变了的时候

也指出了这就是阿里云不推荐使用Lettuce,而使用Jedis的原因

不过遗憾的是,这个issue还处于open状态,还没有解决方法

4. 解决

在网上看到一些同样有好奇心的同学试图解决这个问题,死磕生菜 -- lettuce 间歇性发生 RedisCommandTimeoutException 的深层原理及解决方案

这个同学提供了三种解决方案

  1. 设置 Linux 的 TCP_RETRIES2 参数
  2. 设置 Socket Option 的 TCP_USER_TIMEOUT 参数
  3. 定制 lettuce:增加心跳机制

因为第一种会影响全局,所以没有试验,通过尝试了下面两种,发现都不生效,因为对Netty不是特别熟悉,也没有继续深究

最后怎么解决的,使用定时任务ping Redis Server成功解决

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled; import javax.annotation.Resource; @Configuration
@EnableScheduling
public class RedisScheduleTask { public static final Log log = LogFactory.getLog(RedisScheduleTask.class); @Resource
private StringRedisTemplate dupShowMasterRedisTemplate; // 1 minutes
@Scheduled(fixedRate = 60000)
private void configureTasks() {
log.debug("ping redis");
dupShowMasterRedisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(@NotNull RedisConnection connection) throws DataAccessException {
return connection.ping();
}
});
} }

参考

[1] Add support for disconnect on timeout to recover early from no RST packet failures

[2] 死磕生菜 -- lettuce 间歇性发生 RedisCommandTimeoutException 的深层原理及解决方案

[3] Lettuce Github FAQ

Redis Lettuce长时间超时问题的更多相关文章

  1. 防止shell脚本长时间执行导致ssh超时

    在一些对安全性要求较高的场景下.ssh的超时时间是管理员预先设置好的,在闲置一段时间后ssh连接会自己主动断开. 这样的情况下假设通过ssh运行脚本,而脚本运行时间又比較长的话.会导致sshclien ...

  2. MySql 长时间读数据发生超时的异常 Mysql Reader Exception TimeOut expired

    mysql connector: .net var r = cmd.ExecuteReader() r.Reader()   // <--长时间不停调用 Timeout expired.  Th ...

  3. spring boot 集成 redis lettuce

    一.简介 spring boot框架中已经集成了redis,在1.x.x的版本时默认使用的jedis客户端,现在是2.x.x版本默认使用的lettuce客户端,两种客户端的区别如下 # Jedis和L ...

  4. spring boot 集成 redis lettuce(jedis)

    spring boot框架中已经集成了redis,在1.x.x的版本时默认使用的jedis客户端,现在是2.x.x版本默认使用的lettuce客户端 引入依赖 <!-- spring boot ...

  5. 屏蔽电信流氓广告造成的诡异的问题--Android WebView 长时间不能载入页面

    发如今家里的时候用Android App里的WebView打开站点非常慢,会有十几秒甚至更长时间的卡住. 可是在电脑上打开相同的网页却非常快. 查找这个问题的过程比較曲折,记录下来. 抓取Androi ...

  6. 查看Oracle中存储过程长时间被卡住的原因

    1:查V$DB_OBJECT_CACHE SELECT * FROM V$DB_OBJECT_CACHE WHERE name='CUX_OE_ORDER_RPT_PKG' AND LOCKS!='0 ...

  7. JavaWeb数据库长时间不访问断开链接解决思路

    这几天开发的线上商超系统长时间不操作,会频繁的出现第一次登陆或者跟数据库操作有关的方法都会报500错误,很是鸡肋啊这个问题. 经过网上不断的探索,在知识的海洋里畅游了几分钟后我自己总结出一套方法,我用 ...

  8. Web页面长时间无操作后再获取焦点时转到登录界面

    今天开始讲新浪博客搬到博客园.        在工作中遇到的小问题,感觉有点意思,就记录下来吧!        该问题分为两种情况,一.Web页面长时间无操作后,在对其进行操作,比如点击“首页”.“设 ...

  9. JavaScript长时间未操作自动退出登录

    主要是通过mouseover 来监听有没有进行当前页面操作,通过未操作时间和设定退出的时间做比较,从而退出登录. var oldTime = new Date().getTime(); var new ...

  10. iOS开发笔记--如何实现程序长时间未操作退出

    我们使用金融软件经常会发现手机锁屏或者长时间未操作就会退出程序或者需要重新输入密码等情况.下面让我们看一下如何实现这种功能.我们知道iOS有一个事件循环机制,也就是大家所说的runloop.我们在对程 ...

随机推荐

  1. Typora如何配置gitee图床

    转载自:https://mp.weixin.qq.com/s/5dPLbr2vFgL18XKL1Y05Og 要求: 1.Typora需要升级到最新版 2.需要安装nodejs PicGo软件下载地址: ...

  2. Logstash & 索引生命周期管理(ILM)

    Grok语法 Grok是通过模式匹配的方式来识别日志中的数据,可以把Grok插件简单理解为升级版本的正则表达式.它拥有更多的模式,默认,Logstash拥有120个模式.如果这些模式不满足我们解析日志 ...

  3. 通用 HTTP 签名组件的另类实现

    1.初衷 开发中经常需要做一些接口的签名生成和校验工作,最开始的时候都是每个接口去按照约定单独实现,久而久之就变的非常难维护,因此就琢磨怎么能够写了一个比较通用的签名生成工具. 2.思路 采用链式调用 ...

  4. VMware安装Win11+WSA子系统和使用教程

    VMware安装Win11+WSA子系统和使用教程 作者:Sna1lGo 时间:2022/9/29 下载相关文件: Win11镜像:Download Windows 11 (microsoft.com ...

  5. C++面向对象编程之堆、栈和内存形式

    1.stack 是存在与某个作用域的一块内存空间,当调用函数时,函数就会形成一个stack 存这它的一些参数.返回地址等,生闷气在函数执行完会自动消灭: 2.heap 是操作系统提供的全局的内存空间, ...

  6. 工厂方法在Spring源码中的运用

    我们都知道Spring中IOC是使用的工厂模式,但是对于实现细节就一知半解了,今天这篇文章就带大家解读Spring中是如何使用工厂模式的. 在上篇文章中我们懂了什么是工厂模式,这篇文章就带着学过的概念 ...

  7. AI带你省钱旅游!精准预测民宿房源价格!

    作者:韩信子@ShowMeAI 数据分析实战系列:https://www.showmeai.tech/tutorials/40 机器学习实战系列:https://www.showmeai.tech/t ...

  8. 题解 AT2361 [AGC012A] AtCoder Group Contest

    \(\sf{Solution}\) 显然要用到贪心的思想. 既然最终的结果只与每组强度第二大选手有关,那就考虑如何让他的值尽可能大. 其实,从小到大排个序就能解决,越靠后的值越大,使得每组强度第二大选 ...

  9. 十四、资源控制器之RS

    RC (ReplicationController )主要的作用就是用来确保容器应用的副本数始终保持在用户定义的副本数 .即如果有容器异常退出,会自动创建新的 Pod 来替代:而如果异常多出来的容器也 ...

  10. DQL-聚合函数

    DQL-聚合函数 SQL基本函数,聚合函数对一组值执行计算,并返回单个值,也被称为组函数. 聚合函数对一组值执行计算并返回单一的值.除 COUNT 以外,聚合函数忽略空值,如果COUNT函数的应用对象 ...