java连接redis超时问题怎么解决

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java连接redis超时问题怎么解决相关的知识,希望对你有一定的参考价值。

参考技术A 应该是redis本身的服务有问题了
本文所针对的连接超时问题所涉及的相关元素如下:
Redis客户端: Jedis (java)
Redis版本 :2.8.12
Redis部署操作系统类型:Linux

正文开始:

No 1.Redis执行大命令(时间复杂度为O(N)的命令)
问题剖析:
a.Redis服务器端通过单线程处理命令,一旦有大命令被执行,Redis将无法及时响应来自客户端的任何命令
关于Redis大命令的监控,可以查看slowlog来观察
b.在使用jedis作为redis客户端时,当redis连接池的配置参数testOnBorrow=true时,默认会在获取redis连接
时,先执行redis的ping方法,而基于原因a,此时redis将无法及时响应,自然会报出time out异常
如何解决:
a.尽量避免使用时间复杂度为O(N)的命令
b.如果无法避免使用时间复杂度为O(N)的命令,则应降低其使用频率,避免在业务高峰期时使用

No 2.Redis单次操作数据包过大
问题分析
a.单次操作数据包过大,且操作频繁,极有可能会导致网络拥堵
b.在使用jedis作为redis客户端时,当redis连接池的配置参数testOnBorrow=true时,默认会在获取redis连接
时,先执行redis的ping方法,而基于原因a,此时redis将无法及时响应,自然会报出time out异常
如何解决:
a.排查代码,确定是否存在大数据(数据条目过多/单条数据过大)操作,将其进行改造,改造方案有两个:
a1.数据拆分,变更数据类型(常见的情况是将java中的collection类型序列化后存入redis的String数据
类型中),如将String数据类型调整为hash/list/set等,这常用于解决单条数据量过大的情况
a2.调整业务逻辑,减少单次数据查询范围(常见的情况如将redis中的整个hash数据取回,在应用程序内存中获取需要的entry),如使用hget等单条查询命令替换hgetall命令

AWS Lambda:Redis ElastiCache 连接超时错误

【中文标题】AWS Lambda:Redis ElastiCache 连接超时错误【英文标题】:AWS Lambda: Redis ElastiCache connection timeout error 【发布时间】:2022-01-02 07:50:42 【问题描述】:

我有一个使用 Node 12 的 lambda 函数。

我需要添加到托管在 AWS ElastiCache 中的 Redis 数据库的新连接。

两者都在一个私有 VPC 中,并且安全组/子网配置正确。

解决方案:

globals.js:

const redis = require('redis');
const redisClient = redis.createClient(
  `redis://$process.env.REDIS_HOST:$process.env.REDIS_PORT/$process.env.REDIS_DB`,
);
redisClient.on('error', (err) => 
  console.log('REDIS CLIENT ERROR:' + err);
);
module.exports.globals = 
  REDIS: require('../helpers/redis')(redisClient),
;

index.js(外部处理程序):

const  globals  = require('./config/globals');
global.app = globals;

const lambda_handler = (event, context, callback) =>  ... 
exports.handler = lambda_handler;

helpers/redis/index.js:

const get = require('./get');
module.exports = (redisClient) => 
  return 
    get:  get(redisClient)
  ;
;

helpers/redis/get.js:

module.exports = (redisClient) => 
  return (key, cb) => 
    redisClient.get(key, (err, reply) => 
      if (err) 
        cb(err);
       else 
        cb(null, reply);
      
    );
  ;
;

函数调用:

app.REDIS.get(redisKey, (err, reply) => 
  console.log(`REDIS GET: $err $reply`);
);

问题: 当将 lambda 超时增加到大于 Redis 超时的值时,我收到此错误:

REDIS CLIENT ERROR:Error: Redis connection to ... failed - connect ETIMEDOUT ...

加法:

我尝试在每次交易后退出/关闭连接:

module.exports = (redisClient) => 

  return (cb) => 

    redisClient.quit((err, reply) => 
      if (err) 
        cb(err);
       else 
        cb(null, reply);
      
    );
  ;
;
app.REDIS.get(redisKey, (err, reply) => 
  console.log(`REDIS GET: $err $reply`);
  if (err) 
    cb(err);
   else 
    if (reply) 
      app.REDIS.quit(() => 
        cb()
      );
    
  
)

错误:

REDIS GET: AbortError: GET 无法处理。连接已关闭。

补充说明:

我必须使用回调,这就是我在上面的示例中传递回调的原因 我正在使用"redis": "^3.0.2" 这不是配置问题,因为缓存在短时间内被访问了数百次,但随后开始出现超时错误。 本地一切正常

【问题讨论】:

【参考方案1】:

这不是配置问题,因为缓存在短时间内被访问了数百次,但随后开始出现超时错误。

我认为是问题的根源,可能是redis数据库大小达到大小限制,无法处理新数据?

可以删除里面的旧数据吗?

Elastic Cache 也可能对新 TCP 客户端的连接有限制,如果它耗尽,新连接将被拒绝,并出现您提到的类似错误消息。

如果 aws lambda 函数中的 redis 客户端无法建立连接,则 aws lambda 函数失败 - 并启动新的。新的lambda函数再连接redis,redis无法处理,又启动了一个lambda函数……

所以,在某一时刻,我们达到了活动 redis 连接的限制,系统陷入了死锁。

我认为您可以暂时停止所有 lambda 函数,并扩展 Elastic Cache redis 数据库。

【讨论】:

单个 ElastiCache for Redis 节点最多支持 65,000 个并发客户端连接。关于一些有用的配置/指标的任何想法,我可以检查其他可能的原因?

以上是关于java连接redis超时问题怎么解决的主要内容,如果未能解决你的问题,请参考以下文章

解决redis连接超时

redis之timeout连接超时问题解决

redis连接超时问题

Java:连接请求超时是啥意思?超时就不再请求了?

接口超时需要怎么处理

解决redis上显示timeout连接超时