redis 连接打满的解决
创始人
2024-04-03 16:53:57
0

先上效果,连接数从10000下降到25,提升400倍;

内存占用,从70%下降到18%,降幅1/4;

 

一、现象

服务用了redis,主要为加锁用,保证唯一性;最初服务正常,后期只要用到redis的地方,不超2分钟,10000的连接数就会被打满,最后造成资源耗尽、服务崩溃。

 

二、分析

阿里云redis最大连接数是10000个,被打满只有2个可能,连接数创建后,要么没释放(销毁),要么在持续不断的创建,且创建数无大于释放数。

怀疑1:连接没被释放

查代码,所有加锁的地方,最终都在finally中作unlock,所以此条被排除、

try{
**业务代码**} catch (Exception e) {
} finally {if (rLock.isLocked()) {if (rLock.isHeldByCurrentThread()) {rLock.unlock();}}
}

怀疑2:连接在不断的创建,且大于销毁数

因为最初的redis是用默认配置,代码如下:

public class RedissonConfig {public static RedissonClient redissonClient() {Config config = new Config();String url = xx.getConfig("rds.url");String pwd = xx.getConfig("rds.pwd");Integer database = Integer.parseInt(xx.getConfig("rds.database"));config.useSingleServer().      .setAddress(url).setPassword(pwd).setDatabase(database);RedissonClient redisson = Redisson.create(config);return redisson;}
}

以为是相关参数没配置,于是把参数加上,然并卵

 config.useSingleServer().setConnectTimeout(10000).setTimeout(3000).setIdleConnectionTimeout(10000).setConnectionPoolSize(16).setConnectionMinimumIdleSize(6).setRetryAttempts(3).setRetryInterval(1500).setAddress(url).setPassword(pwd).setDatabase(database);

后来查到这位博友:单例模式之「双重校验锁」_HoryC的博客-CSDN博客_单例模式双重校验锁

的文章,忽然顿悟,可能是JFinal在实现时,没有默认像SpringBoot一样将redis转为单例,造成不断创建线程连接,从源码可以看出,连接池默认是64,在旧锁未释放前,不断创建,造成打爆

三、解决 

知道原因就好办了,在创建前先作判断,如果存在则直接return,否则创建

public class RedissonConfig {//必须有volatile修饰(防止指令重排序)private volatile static RedissonClient instance;//构造函数必须私有(防止外部通过构造方法创建对象)private RedissonConfig() {}public static RedissonClient redissonClient() {//第一个判空(如果是空,就不必再进入同步代码块了,提升效率)if (instance == null) {//这里加锁,是为了防止多线程的情况下出现实例化多个对象的情况synchronized (RedissonConfig.class) {//第二个判空(如果是空,就实例化对象)if (instance == null) {Config config = new Config();config.setCodec(new org.redisson.client.codec.StringCodec());config.useSingleServer().setConnectionPoolSize(50);//设置对于master节点的连接池中连接数最大为500config.useSingleServer().setIdleConnectionTimeout(100000);//如果当前连接池里的连接数量超过了最小空闲连接数,而同时有连接空闲时间超过了该数值,那么这些连接将会自动被关闭,并从连接池里去掉。时间单位是毫秒。config.useSingleServer().setConnectTimeout(300000);//同任何节点建立连接时的等待超时。时间单位是毫秒。config.useSingleServer().setTimeout(30000);//等待节点回复命令的时间。该时间从命令发送成功时开始计时。//  不能反序列化 阻塞队列中的string元素Codec codec = new JsonJacksonCodec();config.setCodec(codec);// 你的IPconfig.useSingleServer().setAddress(url).setPassword(pwd).setDatabase(database).setKeepAlive(true);instance = Redisson.create(config);}}}return instance;}
}

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...