翻译文章,原文地址:https://redis.io/docs/reference/clients/
How the Redis server manages client connections
Redis服务如何管理客户端连接
This document provides information about how Redis handles clients at the network layer level: connections, timeouts, buffers, and other similar topics are covered here.
这个文档说明了 Redis处理网络层客户端:连接,超时,缓冲区和其他包含的类似主题。
The information contained in this document is only applicable to Redis version 2.6 or greater.
文档仅适用于 Redis2.6及以上版本
Accepting Client Connections
Redis accepts clients connections on the configured TCP port and on the Unix socket if enabled. When a new client connection is accepted the following operations are performed:
Redis在配置了TCP端口和启用了Unix 套接字启用后 接收客户端连接。当一个新客户端连接被接收,将会执行以下操作。
- The client socket is put in the non-blocking state since Redis uses multiplexing and non-blocking I/O.
客户端套接字设为非阻塞状态,因为Redis使用多路复用非阻塞IO
- The
TCP_NODELAY
option is set in order to ensure that there are no delays to the connection.
TCP_NODELAY
选项被设置以确保连接无延迟。
- A readable file event is created so that Redis is able to collect the client queries as soon as new data is available to read on the socket.
创建一个可读文件事件,这样Redis才可以从客户端队列及时采集从套接字读取的新数据。
After the client is initialized, Redis checks if it is already at the limit configured for the number of simultaneous clients (configured using the maxclients
configuration directive, see the next section of this document for further information).
客户端初始化以后,Redis检查并发客户端连接数是否已经达到配置的限制(直接使用
maxclients
配置的)
When Redis can’t accept a new client connection because the maximum number of clients has been reached, it tries to send an error to the client in order to make it aware of this condition, closing the connection immediately. The error message will reach the client even if the connection is closed immediately by Redis because the new socket output buffer is usually big enough to contain the error, so the kernel will handle transmission of the error.
当Redis因达到最大客户端连接数而无法接受新客户端连接时,它将发给客户端发送错误提示信息,然后立即关闭连接。及时客户端连接立刻被关闭,错误信息也能够到达客户端,因为套接字的输出缓冲区通常足够大到包含错误,所以内核将会处理错误的传输。
What Order are Client Requests Served In?
客户端请求的服务顺序
The order is determined by a combination of the client socket file descriptor number and order in which the kernel reports events, so the order should be considered as unspecified.
该顺序由客户端套接字文件描述符编号和内核报告事件的顺序的组合确定,因此应将该顺序视为未指定。
However, Redis does the following two things when serving clients:
但是,Redis 在为客户端提供服务时会执行以下两项操作:
- It only performs a single
read()
system call every time there is something new to read from the client socket. This ensures that if we have multiple clients connected, and a few send queries at a high rate, other clients are not penalized and will not experience latency issues.
每次从客户端套接字读取新内容时,它只执行一个“read()”系统调用。这可确保如果我们连接了多个客户端,并且有几个客户端以高速率发送查询,则其他客户端不会受到惩罚,也不会遇到延迟问题。
- However once new data is read from a client, all the queries contained in the current buffers are processed sequentially. This improves locality and does not need iterating a second time to see if there are clients that need some processing time.
然而一从客户端读到新数据,在当前缓冲区中包含的所有请求都会被按顺序处理。这改进了局部性,并且不需要再次迭代以查看是否存在需要一些处理时间的客户端。
Maximum Concurrent Connected Clients
最大并发连接客户端
In Redis 2.4 there was a hard-coded limit for the maximum number of clients that could be handled simultaneously.
在Redis 2.4版本,对可以并发处理的客户端的最大数量有了一个硬编码的限制
In Redis 2.6 and newer, this limit is dynamic: by default it is set to 10000 clients, unless otherwise stated by the maxclients
directive in redis.conf
.
在Redis2.6及以后的版本,这个限制是动态的:默认设置为10000个客户端,除非直接在
redis.conf
中配置maxclients
。
However, Redis checks with the kernel what the maximum number of file descriptors that we are able to open is (the soft limit is checked). If the limit is less than the maximum number of clients we want to handle, plus 32 (that is the number of file descriptors Redis reserves for internal uses), then the maximum number of clients is updated to match the number of clients it is really able to handle under the current operating system limit.
但是,Redis会与内核一起检查我们能够打开的文件描述符的最大数量是多少(选中了*soft limit*)。如果该限制小于我们要处理的最大客户端数加上32(即Redis为内部使用保留的文件描述符数),那么最大客户端数将被更新,以匹配当前操作系统限制下它“真正能够处理”的客户端数。
When maxclients
is set to a number greater than Redis can support, a message is logged at startup:
当
maxclients
被设置为超过Redis可以支持的数量,在启动时会在日志中输出信息:
$ ./redis-server --maxclients 100000
[41422] 23 Jan 11:28:33.179 # Unable to set the max number of files limit to 100032 (Invalid argument), setting the max clients configuration to 10112.
When Redis is configured in order to handle a specific number of clients it is a good idea to make sure that the operating system limit for the maximum number of file descriptors per process is also set accordingly.
当配置 Redis 以处理特定数量的客户端时,最好确保还相应地设置了每个进程的最大文件描述符数的操作系统限制。
Under Linux these limits can be set both in the current session and as a system-wide setting with the following commands:
Linux系统下,通过以下命令,既可以设置当前session生效,也可以设置为系统范围设置。
ulimit -Sn 100000 # This will only work if hard limit is big enough.
sysctl -w fs.file-max=100000
Output Buffer Limits
输出缓冲区限制
Redis needs to handle a variable-length output buffer for every client, since a command can produce a large amount of data that needs to be transferred to the client.
Redis 需要为每个客户端处理一个可变长度的输出缓冲区,因为命令可能会产生大量需要传输到客户端的数据。
However it is possible that a client sends more commands producing more output to serve at a faster rate than that which Redis can send the existing output to the client. This is especially true with Pub/Sub clients in case a client is not able to process new messages fast enough.
但是,客户端可能会发送更多的命令,从而产生更多的输出,以比 Redis 将现有输出发送到客户端的速率更快的速度提供服务。对于 Pub/Sub 客户端尤其如此,以防客户端无法足够快地处理新消息。
Both conditions will cause the client output buffer to grow and consume more and more memory. For this reason by default Redis sets limits to the output buffer size for different kind of clients. When the limit is reached the client connection is closed and the event logged in the Redis log file.
两种条件下都会导致客户端输出缓冲区的增长和小号越来越多的内存。因此,默认情况下,Redis为不同类型的客户端设置输出缓冲区大小限制。当达到限制客户端连接会被关闭并且在日志文件中会记录这个事件。
There are two kind of limits Redis uses:
Redis使用两种限制:
- The hard limit is a fixed limit that when reached will make Redis close the client connection as soon as possible. > 硬限制 是指达到先之后Redis会立即关闭客户端连接。
- The soft limit instead is a limit that depends on the time, for instance a soft limit of 32 megabytes per 10 seconds means that if the client has an output buffer bigger than 32 megabytes for, continuously, 10 seconds, the connection gets closed. > 软限制 是取决于时间的限制,如每10妙32兆的限制意味着如果客户端的输出缓冲区达到了每秒32兆持续了10秒,那么客户端会被关闭。
Different kind of clients have different default limits:
不同类型的客户端有不同的默认限制:
- Normal clients have a default limit of 0, that means, no limit at all, because most normal clients use blocking implementations sending a single command and waiting for the reply to be completely read before sending the next command, so it is always not desirable to close the connection in case of a normal client. > 普通客户端 默认不限制,因为大多数普通客户端使用阻塞实现来发送单个命令,并在发送下一个命令之前等待完全读取回复,所以在正常客户端的情况下,总是不希望关闭连接。
- Pub/Sub clients have a default hard limit of 32 megabytes and a soft limit of 8 megabytes per 60 seconds. > Pub/Sub 客户端 默认硬限制32兆和软限制为8兆持续60秒。
- Replicas have a default hard limit of 256 megabytes and a soft limit of 64 megabyte per 60 seconds. > 副本 默认硬限制256兆和软限制为 64兆持续60秒。
It is possible to change the limit at runtime using the CONFIG SET
command or in a permanent way using the Redis configuration file redis.conf
. See the example redis.conf
in the Redis distribution for more information about how to set the limit.
使用
CONFIG SET
命令可以运行中修改限制或者在配置文件redis.conf
中永久修改。
Query Buffer Hard Limit
查询缓冲区硬限制
Every client is also subject to a query buffer limit. This is a non-configurable hard limit that will close the connection when the client query buffer (that is the buffer we use to accumulate commands from the client) reaches 1 GB, and is actually only an extreme limit to avoid a server crash in case of client or server software bugs.
每个客户端也受查询缓冲区限制的约束。这是一个不可配置的硬限制,当客户端查询缓冲区(即我们用于累积来自客户端的命令的缓冲区)达到 1 GB 时,它将关闭连接,实际上只是一个极端限制,以避免在客户端或服务器软件错误的情况下服务器崩溃。
Client Eviction
客户端驱逐(Redis7.0后才可用)
Redis is built to handle a very large number of client connections. Client connections tend to consume memory, and when there are many of them, the aggregate memory consumption can be extremely high, leading to data eviction or out-of-memory errors. These cases can be mitigated to an extent using output buffer limits, but Redis allows us a more robust configuration to limit the aggregate memory used by all clients’ connections.
Redis 是为处理大量客户端连接而构建的。客户端连接往往会消耗内存,当存在许多客户端连接时,总内存消耗可能非常高,从而导致数据逐出或内存不足错误。这些情况可以使用[输出缓冲区限制](https://redis.io/docs/reference/clients/#output-buffers-limits)在一定程度上得到缓解,但Redis允许我们使用更强大的配置来限制所有客户端连接使用的内存之和。
This mechanism is called client eviction, and it’s essentially a safety mechanism that will disconnect clients once the aggregate memory usage of all clients is above a threshold. The mechanism first attempts to disconnect clients that use the most memory. It disconnects the minimal number of clients needed to return below the maxmemory-clients
threshold.
此机制称为 客户端逐出,它本质上是一种安全机制,一旦所有客户端的总内存使用量超过阈值,它将断开客户端的连接。该机制首先尝试断开使用最多内存的客户端。它会断开返回低于“maxmemory-clients”阈值所需的最小客户端数。
maxmemory-clients
defines the maximum aggregate memory usage of all clients connected to Redis. The aggregation takes into account all the memory used by the client connections: the query buffer, the output buffer, and other intermediate buffers.
maxmemory-clients
定义了连接到 Redis 的所有客户端的最大内存使用量的总和。这个总和会计入客户端连接使用的所有内存:[查询缓冲区](https://redis.io/docs/reference/clients/#query-buffer-hard-limit)、输出缓冲区和其他中间缓冲区。
Note that replica and master connections aren’t affected by the client eviction mechanism. Therefore, such connections are never evicted.
注意主从副本连接不回受连接驱逐机制的影响。因此,这些连接不会驱逐。
maxmemory-clients
can be set permanently in the configuration file (redis.conf
) or via the CONFIG SET
command. This setting can either be 0 (meaning no limit), a size in bytes (possibly with mb
/gb
suffix), or a percentage of maxmemory
by using the %
suffix (e.g. setting it to 10%
would mean 10% of the maxmemory
configuration).
maxmemory-clients
可以在配置文件redis.conf
中永久配置,或者通过CONFIG SET
命令。这个值可以设置为0(将不回限制),以字节为单位的大小(也有可能带有mb
或gb
后缀),或者是以%
为后缀的maxmemory
最大内存的百分比。(如设置 10% 意思是最大内存的10%)
The default setting is 0, meaning client eviction is turned off by default. However, for any large production deployment, it is highly recommended to configure some non-zero maxmemory-clients
value. A value 5%
, for example, can be a good place to start.
默认是设置为0,说明客户端驱逐默认关闭。然而,一些大型的生产部署,强烈推荐配置一些非零的
maxmemory-clients
值。如可以从5%
开始配置。
It is possible to flag a specific client connection to be excluded from the client eviction mechanism. This is useful for control path connections. If, for example, you have an application that monitors the server via the INFO
command and alerts you in case of a problem, you might want to make sure this connection isn’t evicted. You can do so using the following command (from the relevant client’s connection):
可以标记要从客户端逐出机制中排除的特定客户端连接。这对于控制路径连接非常有用。例如,如果您有一个应用程序通过 [‘INFO’](https://redis.io/commands/info) 命令监视服务器,并在出现问题时向您发出警报,则可能需要确保此连接不会被逐出。您可以使用以下命令(从相关客户端的连接)执行此操作:
And you can revert that with:
CLIENT NO-EVICT
off
For more information and an example refer to the maxmemory-clients
section in the default redis.conf
file.
Client eviction is available from Redis 7.0.
客户端驱逐机制从Redis7.0版本开始可用
Client Timeouts
客户端超时时间
By default recent versions of Redis don’t close the connection with the client if the client is idle for many seconds: the connection will remain open forever.
默认最近的Redis版本不回关闭客户端连接如果客户端空闲几秒:连接会永远保持打开状态。
However if you don’t like this behavior, you can configure a timeout, so that if the client is idle for more than the specified number of seconds, the client connection will be closed.
但是,如果您不喜欢这样,则可以配置超时时间,以便在客户端空闲时间超过指定的秒数时,将关闭客户端连接。
You can configure this limit via redis.conf
or simply using CONFIG SET timeout <value>
.
可以在
redis.conf
文件中配置或使用CONFIG SET timeout <value>
。
Note that the timeout only applies to normal clients and it does not apply to Pub/Sub clients, since a Pub/Sub connection is a push style connection so a client that is idle is the norm.
注意这个超时时间只会应用到普通的客户端连接,不会应用到Pub/Sub客户端连接,因为 Pub/Sub连接是一个*推送形式*连接,因此客户端空闲是常态。
Even if by default connections are not subject to timeout, there are two conditions when it makes sense to set a timeout:
即使默认情况下连接不受超时的影响,设置超时也存在两种情况:
- Mission critical applications where a bug in the client software may saturate the Redis server with idle connections, causing service disruption.
任务关键型应用程序,其中客户端软件中的bug可能会使Redis服务器充满空闲连接,从而导致服务中断。
- 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.
作为一种调试机制,以便在客户端软件中的错误使服务器充满空闲连接时能够与服务器连接,从而无法与服务器交互。
Timeouts are not to be considered very precise: Redis avoids setting timer events or running 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.
超时不应被视为非常精确:Redis 避免设置计时器事件或运行O(N)算法来检查空闲客户端,因此检查会不时以增量方式执行。这意味着,当超时设置为 10 秒时,如果同时连接多个客户端,客户端连接可能会在12秒后关闭。
The CLIENT Command
客户端命令
The Redis CLIENT
command allows you to inspect the state of every connected client, to kill a specific client, and to name connections. It is a very powerful debugging tool if you use Redis at scale.
Redis [
CLIENT
](https://redis.io/commands/client) 命令允许您检查每个已连接客户端的状态、终止特定客户端以及命名连接。如果您大规模使用 Redis,它是一个非常强大的调试工具。
CLIENT LIST
is used in order to obtain a list of connected clients and their state:
[
CLIENT LIST
](https://redis.io/commands/client-list) 命令用于获取已连接客户端及其状态的列表:
redis 127.0.0.1:6379> client list
addr=127.0.0.1:52555 fd=5 name= age=855 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
addr=127.0.0.1:52787 fd=6 name= age=6 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
In the above example two clients are connected to the Redis server. Let’s look at what some of the data returned represents:
上面的荔枝是两个客户端连接到Redis服务。返回字段如下:
- addr: The client address, that is, the client IP and the remote port number it used to connect with the Redis server. > addr: 客户端地址,即客户端 IP 和用于与 Redis 服务器连接的远程端口号。
- fd: The client socket file descriptor number. > fd: 客户端套接字文件描述符编号。
- name: The client name as set by
CLIENT SETNAME
. > name: 通过CLIENT SETNAME
设置的客户端名称。 - age: The number of seconds the connection existed for. > age: 连接存在的秒数。
- idle: The number of seconds the connection is idle. > idle: 连接空闲秒数。
- flags: The kind of client (N means normal client, check the full list of flags). > flags: 连接类型(N为普通客户端连接,参考full list of flags)
- omem: The amount of memory used by the client for the output buffer. > omem: 客户端输出缓冲区使用的内存量。
- cmd: The last executed command. > cmd: 最后执行的命令。
See the CLIENT LIST
documentation for the full listing of fields and their purpose.
参考
CLIENT LIST
文档
Once you have the list of clients, you can close a client’s connection using the CLIENT KILL
command, specifying the client address as its argument.
通过客户端连接列表,可以通过
CLIENT KILL
命令关闭指定客户端地址参数的客户端连接。
The commands CLIENT SETNAME
and CLIENT GETNAME
can be used to set and get the connection name. Starting with Redis 4.0, the client name is shown in the SLOWLOG
output, to help identify clients that create latency issues.
CLIENT SETNAME
命令和CLIENT GETNAME
命令可以用来设置和获取连接名称。从Redis4.0开始,客户端名称可以在SLOWLOG
输出中进行展示了,可以用来帮助识别产生延迟问题的客户端。
TCP keepalive
From version 3.2 onwards, Redis has TCP keepalive (SO_KEEPALIVE
socket option) enabled by default and set to about 300 seconds. This option is useful in order to detect dead peers (clients that cannot be reached even if they look connected). Moreover, if there is network equipment between clients and servers that need to see some traffic in order to take the connection open, the option will prevent unexpected connection closed events.
从3.2版起,Redis默认启用TCP keepalive(
SO_KEEPALIVE
套接字选项),并设置为大约300秒。此选项对于检测死机(即使看起来已连接也无法访问的客户端)很有用。此外,如果客户端和服务器之间的网络设备需要查看一些流量才能打开连接,则该选项将防止意外的连接关闭事件。