重传机制概述:为什么需要重传、超时重传与快速重传

TCP 号称可靠传输,但网络环境从来不是完美的。丢包、乱序、延迟抖动——这些才是常态。我做了十几年网络排障,见过太多因为重传配置不当导致业务雪崩的案例。说白了,重传机制就是 TCP 在不可靠的 IP 层之上,自己给自己兜底的一套保命方案。

为什么需要重传?

你想想看,数据发出去之后,发送方怎么知道对方收到了?唯一的证据就是 ACK。如果 ACK 没回来,发送方只能做两种假设:要么数据丢了,要么 ACK 丢了。无论哪种情况,都得重传。

我在项目中遇到过最典型的一个场景:某金融系统的交易网关,白天高峰期突然出现大量超时。抓包一看,TCP 重传率飙到 15%。原因很简单——中间一台交换机缓存满了,把数据包悄悄丢了。如果没有重传机制,那笔交易就永远消失了。

核心结论:重传是 TCP 可靠性的最后一道防线。没有重传,TCP 就退化成 UDP,所有应用层都得自己处理丢包。

超时重传(RTO)基本原理

超时重传是最原始、最直觉的方案:发一个包,开一个定时器,时间到了 ACK 还没回来,我就再发一次。

但问题来了——这个定时器设多久?设短了,网络稍微慢一点就疯狂重传,造成拥塞;设长了,丢包后要等很久才能恢复,用户体验极差。

我记得刚入行时,有个老工程师跟我说过一句话:「RTO 不是拍脑袋定的,是算出来的。」TCP 会动态测量 RTT(往返时间),然后根据 RTT 的波动情况计算 RTO。公式大致是:

RTO = SRTT + max(G, 4 × RTTVAR)

其中:
SRTT   = 平滑后的 RTT(加权平均)
RTTVAR = RTT 的偏差(抖动)
G      = 时钟粒度(通常 1ms 或 10ms)

这个公式的核心思想是:不仅要考虑平均延迟,还要考虑延迟的抖动。如果网络很稳定,RTO 就接近 RTT;如果网络忽快忽慢,RTO 就要留出余量。

我的经验:很多 Linux 服务器默认的 RTO 最小值是 200ms,最大值 120s。但在内网环境(RTT < 1ms),这个 200ms 的下限太保守了。我曾经把某个高吞吐系统的 RTO min 调到 10ms,重传恢复速度提升了近 10 倍。

超时重传还有一个关键细节:指数退避。第一次超时后,RTO 翻倍;第二次再翻倍……直到达到上限。为什么要这样?因为连续超时说明网络可能已经拥塞了,这时候再疯狂重传只会雪上加霜。

重传次数 RTO 值(初始 200ms) 说明
第 1 次 200ms 正常超时
第 2 次 400ms 翻倍
第 3 次 800ms 再翻倍
第 4 次 1.6s 继续翻倍
第 5 次 3.2s 直到达到上限
避坑指南:我曾经遇到过一台服务器因为 RTO 计算异常,导致 RTO 始终等于 RTT + 1ms。结果网络稍微抖动一下,就触发大量虚假重传,把整个出口带宽打满了。排查了三天才发现是内核的 RTT 采样逻辑被某个第三方模块污染了。所以,不要盲目相信默认值,一定要在生产环境验证 RTO 的实际表现。

快速重传原理

超时重传有个致命缺陷——慢。等 RTO 超时,往往已经过去几百毫秒甚至几秒。对于实时性要求高的场景(比如视频会议、在线交易),这个延迟不可接受。

快速重传的思路很巧妙:不用等超时,靠 ACK 来触发。

具体怎么做的?假设发送方发了包 1、2、3、4、5。包 2 丢了,接收方收到包 3 时,发现序号不连续,于是立即回复一个 ACK,确认号还是「期望收到包 2」。收到包 4,再发一个 ACK 要包 2。收到包 5,还是 ACK 要包 2。

当发送方连续收到 3 个相同的 ACK(即重复 ACK 达到阈值),它就知道包 2 大概率丢了,不用等超时,立刻重传。

关键点:快速重传的触发条件是「3 个重复 ACK」,不是 2 个也不是 4 个。为什么是 3?因为乱序也可能导致 1-2 个重复 ACK,3 个是一个比较可靠的丢包信号。这是 TCP 协议设计者经过大量实验得出的经验值。

快速重传相比超时重传的优势很明显:

  • 速度快:通常在几个 RTT 内就能恢复,不用等指数退避
  • 对网络友好:不会像超时重传那样突然爆发大量重传
  • 能配合拥塞控制:触发快速重传的同时,TCP 会启动快速恢复算法,调整拥塞窗口

但快速重传也不是万能的。如果网络丢包率很高,或者接收窗口满了导致接收方不发 ACK,快速重传就失效了,最终还是得靠超时重传兜底。

实战技巧:我在调优 Web 服务器时,经常用 ss -i 查看每个 TCP 连接的 RTO 和重传统计。如果发现快速重传次数远多于超时重传,说明网络状况还不错;反过来,如果超时重传占比很高,那就要检查是不是有防火墙丢包、或者中间设备 buffer 太小了。

两种重传的协作关系

超时重传和快速重传不是互斥的,而是互补的。快速重传负责「快」,超时重传负责「稳」。实际运行中,TCP 会优先尝试快速重传,只有在快速重传无法触发时,才退回到超时重传。

我画了一张图,帮你理清这两种重传的决策流程:

TCP 重传决策流程 发送数据包 等待 ACK 收到 ACK? 正常完成 检查重复 ACK 计数 ≥3 重复 ACK? 快速重传 RTO 超时? 超时重传 快速重传优先 超时重传兜底

从这张图可以看得很清楚:TCP 收到 ACK 后,先判断是不是重复 ACK。如果是,计数加 1;当计数达到 3,立即触发快速重传。如果一直没有收到足够的重复 ACK,那就只能等 RTO 定时器到期,走超时重传的路径。

嗯,这里要注意一个容易被忽略的点:快速重传只重传一个包(那个被确认丢失的包),而超时重传可能会重传整个拥塞窗口的数据。这也是为什么超时重传对网络冲击更大的原因之一。

一句话总结:快速重传是「早发现、早治疗」,超时重传是「最后手段、代价高昂」。一个高效的 TCP 栈,应该让快速重传处理绝大多数丢包,让超时重传只作为应急方案。