redis.conf 中的“tcp-backlog”是啥

Posted

技术标签:

【中文标题】redis.conf 中的“tcp-backlog”是啥【英文标题】:What's "tcp-backlog" in redis.confredis.conf 中的“tcp-backlog”是什么 【发布时间】:2018-01-30 03:49:07 【问题描述】:

我对 redis.conf 中的tcp-backlog 感到困惑:

# TCP listen() backlog.
#
# In high requests-per-second environments you need an high backlog in order
# to avoid slow clients connections issues. Note that the Linux kernel
# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
# make sure to raise both the value of somaxconn and tcp_max_syn_backlog
# in order to get the desired effect.
tcp-backlog 511

tcp-backlog是“完整连接队列”(三次握手完成,here描述的)还是“不完整连接队列”的大小?

如果它的意思是“完整的连接队列”,那么我为什么要提出tcp_max_syn_backlog 来限制不完整的连接队列的大小?

【问题讨论】:

好问题。它是完成的连接队列。 SYN backlog 是独立的。我认为他们没有理由需要跟踪。 【参考方案1】:

tcp-backlog 是接受队列或完成连接队列的大小。

正如你提到的文档所说:

在 Linux 上,情况有所不同,如 listen 系统调用的手册页所述:

在 Linux 2.2 中,TCP 套接字上的 backlog 参数的行为发生了变化。现在它指定等待接受的完全建立的套接字的队列长度,而不是不完整的连接请求的数量。可以使用 /proc/sys/net/ipv4/tcp_max_syn_backlog 设置不完整套接字队列的最大长度。

这意味着当前的 Linux 版本使用带有两个不同队列的第二个选项:一个大小由系统范围设置指定的 SYN 队列和一个大小由应用程序指定的接受队列。

Redis 服务器使用 tcp-backlog 的配置来通过 listen() 指定接受队列的大小。而SYN队列大小由linux的管理员决定。

如果它的意思是“完整的连接队列”,那我为什么要提高 tcp_max_syn_backlog 来限制不完整的连接队列的大小?

提高 tcp_max_syn_backlog 旨在避免缓慢的客户端连接问题。如果有一些慢客户端正在与redis服务器进行3次握手,并且这些客户端读取响应和发送请求的速度很慢,它们会因为速度慢而占用redis服务器的SYN队列很长时间。

在某些情况下,SYN 队列会因为这些低效的客户端而被填满。如果 SYN 队列被填满,redis 服务器将无法接受新的客户端。所以你应该提高 tcp_max_syn_backlog 来处理这个问题。

【讨论】:

【参考方案2】:

tcp-backlog的大小是“完整的连接队列”(三次握手完成,这里描述的)还是“不完整的连接队列”?

tcp-backlog完整连接队列的大小。实际上,Redis 将这个配置作为listen(int s, int backlog) 调用的第二个参数传递。

@GuangshengZuo 对于这个问题已经有了一个很好的答案。所以我会专注于另一个。

如果它意味着“完整的连接队列”,那么我为什么要提高 tcp_max_syn_backlog 来限制不完整的连接队列的大小?

引用您提到的文档:

该实现使用两个队列,一个 SYN 队列(或不完整的连接队列)和一个接受队列(或完整的连接队列)。处于 SYN RECEIVED 状态的连接被添加到 SYN 队列,然后当它们的状态变为 ESTABLISHED 时移动到接受队列,即收到 3 次握手中的 ACK 数据包时。顾名思义,accept 调用的实现只是为了使用来自接受队列的连接。在这种情况下,listen 系统调用的 backlog 参数决定了接受队列的大小。

我们可以看到complete connection queue 中的项目从incomplete connection queue 中移出

如果您有一个大的somaxconn 和一个小的tcp_max_syn_backlog,那么您可能没有足够的项目可以移动到complete connection queue,而complete connection queue 可能永远不会满。许多请求可能在有机会移动到第二个队列之前已经从第一个队列中删除了。

所以只提高somaxconn 的值可能行不通。你必须提高他们两个。

【讨论】:

【参考方案3】:

昨天,我阅读了 Redis In Action 的第 6 章,其中 Joshua Carlton 写道“Redis 发布和订阅的缺点之一 模型是客户端必须始终连接才能接收 消息,断开连接会导致客户端丢失消息,并且 旧版本的 Redis 可能会变得不可用、崩溃或被杀死,如果 订阅者很慢。”

然后,Joshua Carlton 说,“虽然推送消息很有用,但是当客户端由于某种原因不能一直保持连接时,我们会遇到问题。为了解决这个限制,我们将编写两个不同的 pull可以用来替代 PUBLISH/SUBSCRIBE 的消息传递方法。我们将首先从单一收件人消息传递开始,因为它与我们的先进先出队列有很多共同之处。在本节的后面,我们将转移到我们可以有多个消息收件人的方法。有了多个收件人,当我们需要将消息发送给所有收件人时,我们可以替换 Redis PUBLISH 和 SUBSCRIBE,即使他们已断开连接” 我们很想知道将 Redis PUBLISH 和 SUBSCRIBE 替换为 Joshua Carlton 的第 6.5.2 节多接收者发布/订阅替换,而不是利用 UDP 协议来检测和修复断开连接丢失是否会更高效。

 Could we set a high tcp_max_syn_backlog in redis.conf to prevent either of

Joshua Carlson 的单收件人消息传递和多收件人消息传递方法在每秒 20,000 条消息的负载下断开连接,其中每条消息为 20 字节?

【讨论】:

@GuangshengZuo,redis.conf 中的 tcp_max_syn_backlog 会阻止 Joshua Carlson 的单接收者消息传递和多个接收者消息传递方法在每秒 20,000 条消息的负载下断开连接,其中每条消息为 20字节?谢谢。

以上是关于redis.conf 中的“tcp-backlog”是啥的主要内容,如果未能解决你的问题,请参考以下文章

Redis 学习笔记总结

redis 安装与配置

Redis配置参数详解

Redis集群之配置文件详解(待完善)

docker安装redis

docker安装redis