说明:
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