redis报-ERR max number of clients reached错误

说明:
redis报max number of clients错误,可能是因为客户端接入太多,也是可能是因为系统最大文件描述符数过小。

解决:
1.碰到因为客户端接入太多,可以通过修改redis.conf的maxclients XXXX,设置同一时间最大客户端连接数(默认0,表示不限制)来解决。

# netstat -an|grep 6380|wc -l
4602

当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息。不过最好还是了解一下都谁来连接redis的,是不是连接方式有问题,毕竟redis一般是用来做缓存,不太可能有太多的client来连接。
redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数

2.如果是因为系统最大文件描述符数过小,是可以参考以下修改系统最大文件描述符数

# ps -ef|grep redis
root     23427 21683  0 19:08 pts/0    00:00:00 grep redis
root     31886     1  0 11:30 ?        00:00:00 /usr/local/bin/redis-server /data/redis/6379/redis6379.conf

从第二列得到redis的PID为31886

# cat /proc/31886/limits 
Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            10485760             unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             65535                65535                processes 
Max open files            65535                65535                files     
Max locked memory         32768                32768                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       35840                35840                signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    

Max open files说明此redis进程最大能打开65535个文件描述符(不包含它的子进程或创建出来的线程,65535已经是改过的,原来为1024)。在/proc/31886/task/目录下,详细列出了其下的子任务的情况,每个子文件夹里同样有一个limits文件,限定了各子任务的情况。

一个进程打开了几个文件描述符呢?

# ll /proc/31886/fd/

 
子目录fd中,详细列出了进程打开的每个文件描述符,同样,/proc/19488/task/XXXX/fd下也会有子任务打开的文件描述符的情况。要知道有几个,执行

# ll /proc/31886/fd/ | wc -l

 
怎样知道一个进程及其子进程和哪些文件有关联呢?lsof可以完成这工作。请注意,关联文件和打开文件描述符是两个不同的概念,关联文件的数量可能远远大于打开的文件描述符的数量。

# lsof | grep redis | wc –l  //也可以用父进程的PID过滤
# lsof | grep 31886 | wc –l   //我这里得到的值是9525

 
知道了是系统最大文件描述符数,要怎样修改文件描述符数呢?

# ulimit -SHn 2048  //可以通过ulimit临时修改,但是这样只能影响到当前的session,当终端重新连接或当前用户退出,配置就失效了。想永久变更需编辑/etc/security/limits.conf 文件,添加如下两行:
* hard nofile 2048
* soft nofile 2048
如果进程已经开启,特别是线上业务。如果不想重启进程的话,怎么动态修改呢?
# echo -n ‘Max open files=65535:65535’ > /proc/31886/limits  

 
内核参数对文件描述符也有限制,如果设置的值大于内核的限制,也是不行的:

# sysctl -a|grep file-max   //查找file-max的内核参数:
# sysctl -w file-max=65535   //更改file-max的内核参数
Sysctl也是临时的,要想永久生效,可以通过更改sysctl的文件,编辑/etc/sysctl.conf文件,添加或修改以下一行:
fs.file-max=65535

 
总结:
需要注意的是,文件描述符的限制,不局限于这里描述的这些,还可能和进程的启动参数、用户的环境设置有关。当然,如果是进程BUG造成文件描述符没有及时关闭回收,这增大限制也只是治标,根本上还得修复BUG。
此外,lsof会列出系统中所占用的资源,但是这些资源不一定会占用打开的文件描述符(比如共享内存,信号量,消息队列,内存映射.等,虽然占用了这些资源,但不占用打开文件号),因此有可能出现cat /proc/sys/fs/file-max 的值小于lsof | wc -l

发表评论

邮箱地址不会被公开。 必填项已用*标注