背压与有序投递
背压(Backpressure)
流的输入工作者以数据源允许的速度读取,而处理器与输出各自按自己的速度工作。如果没有界限,慢的处理器会让批次在内存中无限制地堆积,最终将其耗尽。
ArkFlow 用输入工作者与处理器工作者之间通道上的背压(backpressure)阈值来约束这一点。当该通道中在途(挂起)的消息数超过 1024 时,输入工作者会阻塞,直到处理器消化到在途数量重新降到阈值以下为止。
实际效果:
- 数据源的读取速度不会快于流水线能够吸收的速度;
- 持续负载下内存占用保持有界;
- 可重放的数据源只是暂停拉取,因此不会丢失数据(broker 会保留它们)。
对于窗口缓冲(滚动 / 滑动 / 会话),缓冲本身会保存批次直到窗口关闭,因此该阈值会与窗口大小和刷新间隔相互作用——请合理设置窗口大小,避免阻塞输入。
有序输出
处理器工作者并行运行(thread_num > 1),因此批次可能乱序完成。尽管如此,输出工作者仍会按输入产生它们的顺序写入,靠序列号实现:
- 从输入接收的每个批次都会获得一个单调递增的序列号;
- 输出工作者跟踪下一个期望的序列号,在写入更早完成的批次之前,先等待乱序的批次到位;
- 原子计数器记录下一个期望的序列号,因此向 sink 的写入严格按输入顺序发生。
这对顺序可被观察到的 sink 很重要(Kafka 分区键、自身无排序的 SQL 表、追加写文件)。源侧确认(对齐 / ack)只在输出确认写入之后发生,这正是至少一次(at-least-once)契约得以成立的原因——参见投递语义。