解决Redis 连接池报错:ERR max number of clients reached

前言

redis maxclients 是redis server的重要配置,它决定了客户端的最大连接数量,最大客户端连接数量。由于redis不区分连接是客户端连接还是内部打开文件或者和slave连接等,所以maxclients最小存在32个连接数,如果超过了设置的maxclients,redis会给新的连接发送"max number of clients reached",并关闭连接。

在Redis 2.4中,可以同时处理的最大客户端数量存在硬编码限制。 在Redis 2.6中,此限制是动态的:默认情况下,它设置为10000个客户端,除非Redis.conf中的maxclients指令另有说明。

解决思路

绝大部分原因是由于客户端很多空闲连接都没有被及时释放掉从而导致connected_clients非常高,其他可能就是maxclients设置的太少了,或者就是软硬件存在限制。

客户端

  1. 设置超时时间
JedisPoolConfig jedisPoolConfig = initPoolConfig();    
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379);  
================================================>
JedisPoolConfig jedisPoolConfig = initPoolConfig();    
jedisPool = new JedisPool(jedisPoolConfig, "*.*.*.*", 6379,2*1000); 
  1. 回收连接资源
	Jedis jedis = JedisUtils.getJedis();
	try {
             //Todo 
    }catch (Exception e){
        throw new RuntimeException(e.getMessage(), e);
        JedisUtils.returnBrokenResource(jedis);
    }finally {
        JedisUtils.returnResource(jedis);
    }
    /**
	 * 回收Jedis对象资源
	 * 
	 * @param jedis
	 */
	public synchronized void returnResource(Jedis jedis) {
		if (jedis != null) {
			jedisPool.returnResource(jedis);
		}
	}
 
	/**
	 * Jedis对象出异常的时候,回收Jedis对象资源
	 * 
	 * @param jedis
	 */
	public synchronized void returnBrokenResource(Jedis jedis) {
		if (jedis != null) {
			jedisPool.returnBrokenResource(jedis);
		}
 
	}

在Jedis 2.6.2 以后,由于重写了jedis.close(),实现自动关闭,2.6.3以后正式使用,详见Deprecates JedisPool returnResource and returnBrokenResource,这样可以代码使用JDK7中新增的try-with-resource语法糖,这样代码会简洁很多如下:

    try (Jedis jedis = JedisUtils.getJedis()) {
        //Todo 
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    }

后续贴一个JedisUtils工具类

服务端

断开空闲连接

建议先断开部分客户端,不然由于报错:max number of clients reached,无法创建连接。

  1. 使用redis-cli进入命令行,使用info clients 查看客户端连接数,然后使用client list查看当前连接的客户端。

在这里插入图片描述

  1. 设置参数timeout(客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能)自动断开连接,键入config set timeout 600在这里插入图片描述
    可以看到连接数由3430变为709减低了不少,当然也可以选择使用CLIENT KILL命令来杀掉客户端连接。
    -------------------------到此这个问题基本可以解决,下面部分选读-----------------------------------------
设置maxclients
  • 配置文件redis.conf
maxclients 10000
  • 启动参数
$ ./redis-server --maxclients 10000
  • 命令
CONFIG set maxclients 10000

系统平台

由于创建连接数需要分配和消耗系统资源,所以在设置maxclients的时候系统是有预设限制的,如上,10000个连接数是现在redis版本的默认值,由于系统软硬件限制,redis-server启动时候是无法分配到资源的

$ ./redis-server --maxclients 10000
[41422] 23 Jan 11:28:33.179 # Unable to set the max number of files limit to 10032 (Invalid argument), setting the max clients configuration to 4096.
# 获取redis PID
$ ps -ef | grep redis-server
# 获取redis的能够打开的最大文件描述符
cat /proc/{PID}/limints

在这里插入图片描述
图中Max open file这行参数可以看得到进程能够打开的最大文件描述符为4096(ll /proc/{PID}/fd | wc -l可以查看已经产生的个数)并非10000,受到了软硬件限制,这可能产生报错的最根本原因
为了设置maxclients这个参数,官网给与了解决方案,使用ulimit为系统范围的设置,详见Maximum number of clients

在这里插入图片描述
这个方式的前置条件是 hard limit is big enough ,会看上面的截图,Max open file的硬件限制也是4096,达到了最大值,于是有了如下的解决方案

  1. 编辑/etc/security/limits.conf
# 具体设置多少根据实际情况而定
* soft nofile 65536      # open files  (-n)
* hard nofile 65536
 
* soft nproc 65565
* hard nproc 65565       # max user processes   (-u)
  1. 保存重新登录服务器即可
    在这里插入图片描述

参考文章

Redis是一种开源的内存数据库,用于数据缓存和存储。当使用jedis客户端连接Redis时,可能会遇到一些异常情况。其中一种异常是"redis.clients.jedis.exceptions.jedisdataexception: err wrong number of arguments",意为参数个数错误。 该异常通常是由于Redis命令的参数个数不匹配引起的。在使用jedis发送Redis命令时,如果命令所需的参数数量与实际传递的参数数量不一致,就会触发该异常。 发生这种异常的原因可能有几种: 1. 参数个数不足:当执行某个Redis命令时,如果没有提供足够的参数,就会抛出该异常。例如,执行"SET"命令时,至少需要两个参数:key和value,如果只提供了一个参数就会触发异常。 2. 参数个数过多:同样地,当执行Redis命令时,如果提供了多于所需数量的参数,也会引发该异常。Redis命令的参数数量是固定的,如果传递的参数超过了该数量,就会抛出异常。 3. 参数类型错误:有些Redis命令对参数的类型有特定的要求。如果传递了错误类型的参数,也可能会导致该异常的发生。 解决该异常的方法是确保传递给Redis命令的参数数量和类型与命令的要求一致。可以通过参考Redis官方文档或jedis客户端的使用手册来了解每个命令的参数要求。 此外,还需要确保使用正确的方法调用来执行Redis命令,例如使用正确的方法名称和正确的参数顺序。 总结起来,redis.clients.jedis.exceptions.jedisdataexception: err wrong number of arguments异常是由于Redis命令的参数数量或类型不正确导致的。通过检查参数的数量和类型是否与命令要求一致,可以解决此异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值