解决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解决Redis 连接池报错:ERR max number of clients reached_第1张图片
    可以看到连接数由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

解决Redis 连接池报错:ERR max number of clients reached_第2张图片
图中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 连接池报错:ERR max number of clients reached_第3张图片

参考文章

  • JedisPool returnResource and returnBrokenResource https://github.com/xetorthio/jedis/pull/912
  • redis报错“max number of clients reached" https://blog.51cto.com/11819159/1916133
  • Redis连接的客户端数过高 https://blog.csdn.net/cxhgg/article/details/67640263
  • Redis Clients Handling https://redis.io/topics/clients#maximum-number-of-clients
  • linux中ulimit作用 https://www.cnblogs.com/kongzhongqijing/p/5784293.html

你可能感兴趣的:(redis)