背景
在字节跳动的实时计算场景中,我们有很多任务(数量 2k+)会直接服务于线上,其输出时延和稳定性会直接影响线上产品的用户体验,这类任务通常具有如下特点:
流量大,并发高(最大的任务并行度超过 1w)
拓扑类似于多流 Join,将各个数据源做整合输出给下游,不依赖 Checkpoint
没有使用 Checkpoint 并且对短时间内的小部分数据丢失不敏感(如 0.5%),但对数据输出的持续性要求极高
在 Flink 现有的架构设计中,多流 Join 拓扑下单个 Task 失败会导致所有 Task 重新部署,耗时可能会持续几分钟,导致作业的输出断流,这对于线上业务来说是不可接受的。
针对这一痛点,我们提出单点恢复的方案,通过对 network 层的增强,使得在机器下线或者 Task 失败的情况下,以短时间内故障 Task 的部分数据丢失为代价,达成以下目标:
作业不发生全局重启,只有故障 Task 发生 Failover
非故障 Task 不受影响,正常为线上提供服务
解决思路
当初遇到这些问题的时候,我们提出的想法是说能不能在机器故障下线的时候,只让在这台机器上的 Tasks 进行 Failover,而这些 Tasks 的上下游 Tasks 能恰好感知到这些失败的 Tasks,并作出对应的措施:
上游:将原本输出到 Failed Tasks 的数据直接丢弃,等待 Failover 完成后再开始发送数据。
下游:清空 Failed Tasks 产生的不完整数据,等待 Failover 完成后再重新建立连接并接受数据
根据这些想法我们思考得出几个比较关键点在于:
如何让上下游感知 Task Failed ?
如何清空下游不完整的数据 ?
Failover 完成后如何与上下游重新建立连接 ?
基于以上考虑我们决定基于已有的 Network 层线程模型,修改上下游对于 Task Failed 后的处理逻辑,让非故障的 Tasks 短时间内完成对失败 Task 的感知操作,从而使得作业持续稳定地输出。
当前架构
注:我们的实现基于 Flink-1.9,1.11 后的网络模型加入了 Unaligned Checkpoint 的特性,可能会有所变化。
我们先将 Flink 的上下游 Task 通信模型简单抽象一下:

上下游 Task 感知彼此状态的逻辑,分三种情况考虑:
Task 因为逻