跳到主要内容
版本:Next

背压与有序投递

背压(Backpressure)​

流的输入工作者以数据源允许的速度读取,而处理器与输出各自按自己的速度工作。如果没有界限,慢的处理器会让批次在内存中无限制地堆积,最终将其耗尽。

ArkFlow 用输入工作者与处理器工作者之间通道上的背压(backpressure)阈值来约束这一点。当该通道中在途(挂起)的消息数超过 1024 时,输入工作者会阻塞,直到处理器消化到在途数量重新降到阈值以下为止。

实际效果:

  • 数据源的读取速度不会快于流水线能够吸收的速度;
  • 持续负载下内存占用保持有界;
  • 可重放的数据源只是暂停拉取,因此不会丢失数据(broker 会保留它们)。

对于窗口缓冲(滚动 / 滑动 / 会话),缓冲本身会保存批次直到窗口关闭,因此该阈值会与窗口大小和刷新间隔相互作用——请合理设置窗口大小,避免阻塞输入。

有序输出​

处理器工作者并行运行(thread_num > 1),因此批次可能乱序完成。尽管如此,输出工作者仍会按输入产生它们的顺序写入,靠序列号实现:

  • 从输入接收的每个批次都会获得一个单调递增的序列号;
  • 输出工作者跟踪下一个期望的序列号,在写入更早完成的批次之前,先等待乱序的批次到位;
  • 原子计数器记录下一个期望的序列号,因此向 sink 的写入严格按输入顺序发生。

这对顺序可被观察到的 sink 很重要(Kafka 分区键、自身无排序的 SQL 表、追加写文件)。源侧确认(对齐 / ack)只在输出确认写入之后发生,这正是至少一次(at-least-once)契约得以成立的原因——参见投递语义。