Redis 客户端处理
Redis 服务器如何管理客户端连接
本文档提供有关 Redis 如何在网络层级别处理客户端的信息:此处介绍了连接、超时、缓冲区和其他类似主题。
本文档中包含的信息仅适用于 Redis 版本 2.6 或更高版本。
接受客户端连接
Redis 接受配置的 TCP 端口和 Unix 套接字(如果启用)上的客户端连接。接受新的客户端连接时,将执行以下作:
- 客户端套接字处于非阻塞状态,因为 Redis 使用多路复用和非阻塞 I/O。
- 这
TCP_NODELAY
选项,以确保连接没有延迟。 - 创建一个可读文件事件,以便 Redis 能够在套接字上读取新数据后立即收集客户端查询。
客户端初始化后,Redis 会检查它是否已达到限制
配置的同时客户端数量(使用maxclients
configuration 指令,请参阅本文档的下一节以了解更多信息)。
当 Redis 由于最大客户端数 已到达,它会尝试向客户端发送错误,以便 让它知道这种情况,立即关闭连接。 即使连接为 Redis 会立即关闭,因为新的 socket 输出缓冲区通常是 足够大以包含错误,因此内核将处理传输 的错误。
客户端请求的服务顺序是什么?
顺序由 Client 端套接字文件描述符的组合确定 number 和顺序,因此顺序应该是 被视为未指定。
但是,Redis 在为客户端提供服务时会执行以下两项作:
- 它只执行单个
read()
system 调用。这可确保如果我们连接了多个客户端,并且少数客户端以高速率发送查询,则其他客户端不会受到惩罚,也不会遇到延迟问题。 - 但是,一旦从客户端读取新数据,当前缓冲区中包含的所有查询都将按顺序处理。这提高了局部性,并且不需要第二次迭代来查看是否有需要一些处理时间的客户端。
最大并发连接客户端数
在 Redis 2.4 中,最大客户端数有一个硬编码限制 这可以同时处理。
在 Redis 2.6 及更高版本中,此限制可使用maxclients
指令redis.conf
.默认值为 10,000 个客户端。
但是,Redis 会使用内核检查最大文件数 我们能够打开的描述符是 (选中 Soft Limit)。如果 limit 小于我们想要处理的最大客户端数,加上 32(即 Redis 保留供内部使用的文件描述符的数量), 然后,最大客户端数将更新以匹配该数量 在当前作系统下它真正能够处理的客户 限制。
什么时候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.
当配置 Redis 以处理特定数量的客户端时,它会 最好确保作系统的最大 每个进程的文件描述符数量也会相应地设置。
在 Linux 下,这些限制既可以在当前会话中设置,也可以在 系统范围的设置:
ulimit -Sn 100000 # This will only work if hard limit is big enough.
sysctl -w fs.file-max=100000
Output Buffer Limits(输出缓冲器限制)
Redis 需要为每个客户端处理一个可变长度的输出缓冲区,因为 命令可以生成大量数据,需要传输到 客户。
但是,客户端可能会发送更多命令,从而产生更多输出 以比 Redis 将现有输出发送到 客户。如果客户端不是 Pub/Sub 客户端,则尤其如此 能够足够快地处理新消息。
这两种情况都会导致客户端输出缓冲区增长和消耗 越来越多的内存。因此,默认情况下,Redis 会对 output buffer size 的大小。达到限制时 客户端连接已关闭,事件记录在 Redis 日志文件中。
Redis 使用两种限制:
- 硬限制是一个固定限制,达到该限制后,Redis 会尽快关闭客户端连接。
- 相反,软限制是取决于时间的限制,例如,每 10 秒 32 MB 的软限制意味着如果客户端的输出缓冲区连续 10 秒大于 32 MB,则连接将关闭。
不同类型的客户端具有不同的默认限制:
- 普通客户端的默认限制为 0,这意味着根本没有限制,因为大多数普通客户端使用阻塞实现发送单个命令并等待回复被完全读取后再发送下一个命令,因此在普通客户端的情况下关闭连接总是不可取的。
- Pub/Sub 客户端的默认硬限制为 32 MB,软限制为每 60 秒 8 MB。
- 副本的默认硬限制为 256 MB,软限制为每 60 秒 64 MB。
可以在运行时使用CONFIG SET
命令或永久使用 Redis 配置文件redis.conf
.查看示例redis.conf
,了解有关如何设置限制的更多信息。
查询缓冲区硬限制
每个客户端还受查询缓冲区限制的约束。这是一个不可配置的硬限制,当客户端查询缓冲区(即我们用来从客户端累积命令的缓冲区)达到 1 GB 时,它将关闭连接,实际上只是一个极端限制,以避免在客户端或服务器软件错误的情况下服务器崩溃。
客户端驱逐
Redis 旨在处理大量客户端连接。 客户端连接往往会消耗内存,当客户端连接很多时,总内存消耗可能非常高,从而导致数据逐出或内存不足错误。 使用输出缓冲区限制可以在一定程度上缓解这些情况,但 Redis 允许我们使用更健壮的配置来限制所有客户端连接使用的聚合内存。
这种机制称为客户端驱逐,它本质上是一种安全机制,一旦所有客户端的聚合内存使用量超过阈值,它就会断开客户端的连接。
该机制首先尝试断开使用最多内存的客户端的连接。
它会断开返回低于maxmemory-clients
门槛。
maxmemory-clients
定义连接到 Redis 的所有客户端的最大聚合内存使用量。
聚合考虑了客户端连接使用的所有内存:查询缓冲区、输出缓冲区和其他中间缓冲区。
请注意,副本连接和 master 连接不受客户端驱逐机制的影响。因此,此类连接永远不会被驱逐。
maxmemory-clients
可以在配置文件 (redis.conf
) 或通过CONFIG SET
命令。
此设置可以是 0(表示无限制)、以字节为单位的大小(可能为mb
/gb
suffix)、
或maxmemory
通过使用后缀(例如,将其设置为%
10%
意味着maxmemory
配置)。
默认设置为 0,表示客户端逐出默认处于关闭状态。
但是,对于任何大型生产部署,强烈建议配置一些非零maxmemory-clients
价值。
一个值5%
,例如,可能是一个很好的起点。
可以将要从客户端逐出机制中排除的特定客户端连接进行标记。
这对于控制路径连接非常有用。
例如,如果您有一个应用程序通过INFO
命令并提醒您,如果出现问题,您可能希望确保此连接未被逐出。
您可以使用以下命令(从相关客户端的连接)执行此作:
你可以用以下方法恢复它:
CLIENT NO-EVICT
off
有关更多信息和示例,请参阅maxmemory-clients
部分redis.conf
文件。
客户端逐出从 Redis 7.0 开始提供。
客户端超时
默认情况下,最新版本的 Redis 不会关闭与客户端的连接 如果客户端空闲数秒:连接将永远保持打开状态。
但是,如果您不喜欢此行为,则可以配置超时,以便 如果客户端空闲时间超过指定的秒数,则客户端连接将关闭。
您可以通过以下方式配置此限制redis.conf
或者简单地使用CONFIG SET timeout <value>
.
请注意,超时仅适用于普通客户端,不适用于 Pub/Sub 客户端,因为 Pub/Sub 连接是推送式连接,因此客户端处于空闲状态是常态。
即使默认情况下连接不受超时的约束,在两种情况下设置超时也是有意义的:
- 客户端软件中的错误可能会使 Redis 服务器处于空闲连接状态,从而导致服务中断的任务关键型应用程序。
- 作为一种调试机制,以便在客户端软件中的错误使服务器因空闲连接而饱和时能够与服务器连接,从而无法与服务器交互。
超时不应被视为非常精确:Redis 避免设置计时器事件或运行 O(N) 算法来检查空闲的客户端,因此会不时以增量方式执行检查。这意味着,当超时设置为 10 秒时,客户端连接可能会关闭,例如,如果同时连接了多个客户端,则在 12 秒后关闭。
CLIENT 命令
雷迪斯CLIENT
command 允许您检查每个已连接客户端的状态、终止特定客户端以及命名连接。如果您大规模使用 Redis,它是一个非常强大的调试工具。
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
在上面的示例中,两个客户端连接到 Redis 服务器。让我们看看返回的一些数据代表了什么:
- addr:客户端地址,即客户端 IP 和用于连接 Redis 服务器的远程端口号。
- fd:客户端套接字文件描述符编号。
- name:客户端名称,由
CLIENT SETNAME
. - age:连接存在的秒数。
- idle:连接空闲的秒数。
- flags: 客户端的种类(N 表示普通客户端,请查看 flags 的完整列表)。
- omem:客户端用于输出缓冲区的内存量。
- cmd:最后执行的命令。
请参阅 [CLIENT LIST
](/commands/client-list) 文档,了解字段的完整列表及其用途。
获得客户端列表后,您可以使用CLIENT KILL
命令,指定客户端地址作为其参数。
命令CLIENT SETNAME
和CLIENT GETNAME
可用于设置和获取连接名称。从 Redis 4.0 开始,客户端名称显示在SLOWLOG
output,以帮助识别造成延迟问题的客户端。
TCP keepalive
从版本 3.2 开始,Redis 具有 TCP keepalive (SO_KEEPALIVE
socket 选项)并设置为大约 300 秒。此选项可用于检测失效对等体(即使看起来已连接也无法访问的客户端)。此外,如果客户端和服务器之间存在网络设备,需要查看一些流量才能打开连接,则该选项将防止意外的连接关闭事件。