获取服务器支持的最大文件描述符数(该 值会限制你的最大文件打开数,对我们而言,关心的是可供打开的socket的数量)
linux机器可以使用 ulimit 命令获取你关心的一些指数
可以看到支持的最大文件描述符数是4000
也可以直接通过 ulimit -n 获取文件描述符数
还可以通过该命令修改最大文件描述符数
在我们线上机器系统配置文件对应位置为:/etc/sysctl.conf,目前我们线上机器配置的最大文件描述符数为655350
关于redis配置文件一些参数的理解:
daemonize no/yes Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程(我个人是理解就是设置为yes可以支持后台运行redis)
port 6379 指定Redis监听端口,默认端口为6379
bind 127.0.0.1 绑定的主机地址
timeout 300 当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
databases 16 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
maxclients 128 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息(所以想要让redis支持更多的连接数,需要将文件描述符数和maxclients同时设置的大一些,而最终的最大连接数取决于二者较小的那个值)
通过以上两种设置,貌似redis已经可以支持大量的客户端连接了,但是采用 redis-benchmark 进行压力测试,会出现如下错误:
-- Could not connect to Redis at IP:PORT,Cannot assign requested address.
这是因为redis-benchmark的压力测试时频繁的连服务器,数据量较大的时候,由于每次连接都在很短的时间内结束,导致很多的TIME_WAIT,以至于用光了可用的端口号,所以新的连接没办法绑定端口,即“Cannot assign requestedaddress”。
可以通过 netstat -ant|grep TIME_WAIT 过滤出来大量的未关闭连接,效果大概是下边这个样子
这时,你需要让系统知道对于这种TIME_WAIT的TCP连接应该快速回收,以释放端口,供更多的客户端可以请求分配到端口并访问我们的redis
命令如下:
sysctl -w net.ipv4.tcp_timestamps=1 #开启对于TCP时间戳的支持,若该项设置为0,则下面一项设置不起作用
sysctl -w net.ipv4.tcp_tw_recycle=1 #表示开启TCP连接中TIME-WAIT sockets的快速回收
执行后,利用 redis-benchmark 做压力测试,不会再出现 Cannot assign requested address 这个错误
redis-benchmark 压力测试命令:
redis-benchmark -h 127.0.0.1 -p 6379 -c 20000 -n 20000 (h对应参数为ip,p对应参数为端口,c对应参数为并发连接数,n对应参数为请求数量)
这时,你可以看到高并发时 redis 对于不同操作的平均响应时长(只截取部分结果)
在xadtest这台机器上测试20000并发连接数,20000个请求的效果数据如图(可以看到最长响应时长已经达到577ms,目前我们线上服务器的平均响应时长为110ms左右;PS:可能线上的服务器响应效果会好一些,但是有业务在跑,就没做测试):
需要额外提一点:上边提到要让服务器快速关闭TIME_WAIT的TCP连接,会对系统设置做两个修改
sysctl -w net.ipv4.tcp_timestamps=1
sysctl -w net.ipv4.tcp_tw_recycle=1
但是目前我们线上服务器配置文件里的内容为:
#时间戳可以避免序列号的卷绕。一个1Gbps的链路肯定会遇到以前用过的序列号。时间戳能够让内核接受这种“异常”的数据包。这里需要将其关掉
net.ipv4.tcp_timestamps = 0 (与上述修改是有冲突存在的)
#开启TCP连接复用功能,允许将time_wait sockets重新用于新的TCP连接(主要针对time_wait连接)
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
贸然更改系统配置,是会影响我们的线上服务的,测试操作请上测试机!!!
本文内容在类linux环境使用,不适用mac/windows
后续如果涉及到redis集群,会再做补充