4. TCP 重传机制概述:超时重传 (RTO)、快速重传、选择性确认 (SACK)

TCP 协议通过确认与重传机制保证数据的可靠交付。当发送端发出的数据段在传输过程中丢失、损坏或延迟到达时,接收端无法产生对应的确认 (ACK),发送端必须通过某种手段检测到丢失并重新发送数据。本章深入剖析三种核心重传机制:超时重传 (RTO)、快速重传 与 选择性确认 (SACK),帮助运维人员理解不同场景下的重传触发逻辑与优化方向。

排查要点: 网络丢包率超过 0.1% 时,TCP 重传事件会显著增加。区分超时重传与快速重传的比例,是定位丢包原因(拥塞 vs. 随机丢包)的关键第一步。

4.1 超时重传 (Retransmission Timeout, RTO)

超时重传是最基础、最保守的重传机制。发送端为每个发送的数据段启动一个定时器,若在定时器到期前未收到该数据段的 ACK,则判定该数据段丢失,立即重传并重置定时器。

4.1.1 RTO 计算与指数退避

RTO 的值并非固定,而是基于实时测量的 往返时间 (RTT) 动态计算。标准算法如下:

  • SRTT (Smoothed RTT):平滑后的 RTT,反映网络延迟趋势。
  • RTTVAR (RTT Variation):RTT 的偏差,反映延迟抖动。
  • RTO = SRTT + max(G, 4 × RTTVAR),其中 G 为时钟粒度。

当发生超时重传后,TCP 会执行 指数退避 (Exponential Backoff):下一次 RTO 值翻倍,直到达到上限(通常为 60 秒或 120 秒),以减轻网络拥塞。

重传次数 RTO 倍数 典型 RTO 值 (初始 200ms) 说明
1 1× 200 ms 首次超时
2 2× 400 ms 指数退避
3 4× 800 ms 继续退避
4 8× 1.6 s 持续退避
5+ 16× … ≥ 3.2 s 上限 60-120s
运维警示: 频繁的超时重传通常意味着网络存在严重拥塞或长链路故障。指数退避会导致应用层感知到明显的“卡顿”或“连接挂起”,是用户体验下降的直接原因。

4.1.2 超时重传流程 SVG

超时重传 (RTO) 流程 发送端 接收端 数据段 Seq=1 启动 RTO 定时器 定时器到期 重传数据段 Seq=1 ACK (确认收到) 关键特征 发送端等待超时后才重传,延迟大;适用于严重丢包或网络完全中断场景

4.2 快速重传 (Fast Retransmit)

快速重传是一种比超时重传更高效的丢包检测机制。它基于接收端发送的 重复 ACK (Duplicate ACK) 来触发,无需等待 RTO 定时器到期。

4.2.1 触发条件与流程

当接收端收到乱序的数据段时,会立即发送一个 ACK,确认最后一个按序收到的字节。发送端连续收到 3 个或更多相同的重复 ACK 时,即可推断后续数据段已丢失,立即重传,无需等待超时。

  • 条件: 收到 3 个重复的 ACK(即总共 4 个相同的 ACK,包含原始 ACK)。
  • 优势: 重传延迟从 RTO(通常数百毫秒)降低到 1 个 RTT(通常数十毫秒)。
  • 限制: 只能重传一个数据段,无法同时恢复多个丢失的数据段。
排查技巧: 在 tcpdump 或 Wireshark 中,快速重传的特征是“TCP Fast Retransmission”标记。如果快速重传占比高,说明网络存在随机丢包或缓冲区溢出,而非严重拥塞。

4.2.2 快速重传流程 SVG

快速重传流程 (基于重复 ACK) 发送端 接收端 数据段 Seq=1 数据段 Seq=2 (丢失) 数据段 Seq=3 重复 ACK (确认 Seq=1) 数据段 Seq=4 重复 ACK (确认 Seq=1) 数据段 Seq=5 重复 ACK 3 (触发快速重传) 快速重传 Seq=2 重传数据段 Seq=2 关键特征 收到 3 个重复 ACK 后立即重传,延迟低;适用于随机丢包场景

4.3 选择性确认 (Selective Acknowledgment, SACK)

SACK 是 TCP 的扩展选项,允许接收端精确告知发送端哪些数据段已成功接收、哪些丢失,从而避免不必要的重传。

4.3.1 SACK 的工作原理

在传统累积确认中,接收端只能确认连续收到的最大序列号,无法告知乱序到达的数据。SACK 通过在 TCP 选项字段中携带 SACK Block,列出已收到的非连续数据块范围。

  • SACK Permitted 选项: 在 TCP 三次握手时协商,双方均支持 SACK 才能启用。
  • SACK Block 格式: 每个 Block 包含 Left Edge 和 Right Edge,表示一段连续已收数据。
  • 最大 Block 数量: 受 TCP 选项长度限制(40 字节),通常最多 4 个 Block。
性能提升: 在丢包率较高的网络(如无线网络)中,启用 SACK 可将重传效率提升 30%-50%,显著减少不必要的重传和带宽浪费。

4.3.2 SACK 与传统 ACK 对比

对比维度 传统累积 ACK SACK
确认粒度 只能确认连续数据 可确认多个非连续数据块
重传效率 低,可能重传已收数据 高,只重传真正丢失的数据
多丢包恢复 需要多次 RTT 一次 RTT 可恢复多个丢包
选项开销 无额外选项 需 2 字节 + 8 字节/Block
兼容性 所有 TCP 实现 需双方协商支持

4.3.3 SACK 工作流程 SVG

SACK 选择性确认工作流程 发送端 接收端 数据段 Seq=1,2,3,4,5 接收缓冲区 已收: 1, 3, 4, 5 丢失: 2 SACK: 已收 1, 3-5 解析 SACK Block 只重传 Seq=2 重传数据段 Seq=2 累积 ACK (确认所有数据) SACK 核心优势 接收端精确告知已收数据范围,发送端只重传真正丢失的数据段,避免带宽浪费 在多个丢包场景下,SACK 可在一个 RTT 内完成所有重传

4.4 三种重传机制对比总结

机制 触发条件 重传延迟 适用场景 效率
超时重传 (RTO) RTO 定时器到期 高 (RTO 值) 严重拥塞、网络中断 低
快速重传 3 个重复 ACK 中 (1 RTT) 随机丢包、轻度拥塞 中
SACK 重复 ACK + SACK Block 低 (1 RTT) 多丢包、高延迟网络 高
实践建议: 现代操作系统默认启用 SACK。在排查重传问题时,优先检查 SACK 是否生效(通过 tcpdump 观察 SYN 包中的 SACK Permitted 选项)。若 SACK 未启用,建议在系统层面开启:
# Linux 查看 SACK 状态
sysctl net.ipv4.tcp_sack
# 启用 SACK
sysctl -w net.ipv4.tcp_sack=1