Redis处理客户端连接的过程如下:
Redis accepts clients connections on the configured listening TCP port and on the Unix socket if enabled. When a new client connection is accepted the following operations are performed:
1.The client socket is put in non-blocking state since Redis uses multiplexing and non-blocking I/O.
2.The TCP_NODELAY option is set in order to ensure that we don't have delays in our connection.
3.A readable file event is created so that Redis is able to collect the client queries as soon as new data is available to be read on the socket.
在客户端初始化后,Redis会检查是否达到最大连接数,若达到了,其会返回客户端一个报错,随后关闭连接。
对于maxclients参数,配置中默认为10000。
# Set the max number of connected clients at the same time. By default
# this limit is set to 10000 clients, however if the Redis server is not
# able to configure the process file limit to allow for the specified limit
# the max number of allowed clients is set to the current file limit
# minus 32 (as Redis reserves a few file descriptors for internal uses).
#
# Once the limit is reached Redis will close all the new connections sending
# an error 'max number of clients reached'.
#
# maxclients 10000
某天收到一个报警,说是连接数不多了,通过client list查看发现连接中有很多idle很大的连接。
id=6665171818 addr=192.168.4.66:56207 fd=374 name= age=172130 idle=172085 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=hmget
id=6576394514 addr=192.168.6.121:43269 fd=545 name= age=378277 idle=84307 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=expire
id=6702222993 addr=192.168.7.147:33843 fd=990 name= age=74926 idle=64641 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=hgetall
其实这些连接都早已不是活跃连接了,Redis提供了一个timeout参数处理这种情况,该参数默认没有开启。
# Close the connection after a client is idle for N seconds (0 to disable)
timeout 0
从最佳实践的角度建议还是开启,如timeout 1800(上述实例设置后,连接释放了很多)。文档也提到开启timeout,可预防两种情况:
1.Mission critical applications where a bug in the client software may saturate the Redis server with idle connections, causing service disruption.
2.As a debugging mechanism in order to be able to connect with the server if a bug in the client software saturates the server with idle connections, making it impossible to interact with the server.
该参数设置的时间并不是精确的,Redis这样也是为了性能的考虑。
Timeouts are not to be considered very precise: Redis avoids to set timer events or to run O(N) algorithms in order to check idle clients, so the check is performed incrementally from time to time. This means that it is possible that while the timeout is set to 10 seconds, the client connection will be closed, for instance, after 12 seconds if many clients are connected at the same time.
同timeout类似,还有一个tcp-keepalive参数,也是断掉异常连接作用,该参数是默认开启的。
# TCP keepalive.
#
# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
# of communication. This is useful for two reasons:
#
# 1) Detect dead peers.
# 2) Take the connection alive from the point of view of network
# equipment in the middle.
#
# On Linux, the specified value (in seconds) is the period used to send ACKs.
# Note that to close the connection the double of the time is needed.
# On other kernels the period depends on the kernel configuration.
#
# A reasonable value for this option is 300 seconds, which is the new
# Redis default starting with Redis 3.2.1.
tcp-keepalive 300
要想从机制上阐述这两个参数作用,又要进入到源码了,再一次说明代码是最直接的生产力。
Redis在处理客户端连接时,还会考虑输入、输出缓冲的限制,可查看“CLIENT LIST中qbuf,qbuf-free和obl,oll,omem的含义”。