Flink中的Fault Tolerance 容错机制( 二 )


上图描述的是一个面描述 增量计算 word count的Job , 上图核心说明了如下几点:

  • barrier 由source节点发出;
  • barrier会将流上event切分到不同的checkpoint中;
  • 汇聚到当前节点的多流的barrier要对齐;
  • barrier对齐之后会进行Checkpointing , 生成snapshot;
  • 完成snapshot之后向下游发出barrier , 继续直到Sink节点;
这样在整个流上面以barrier方式进行Checkpointing , 随着时间的推移 , 整个流的计算过程中按时间顺序不断的进行Checkpointing , 如下图:
Flink中的Fault Tolerance 容错机制文章插图
生成的snapshot会存储到StateBackend中 , 相关State的介绍可以查阅 《Apache Flink 漫谈系列 - State》。 这样在进行failover时候 , 从最后一次成功的checkpoint进行恢复;
Checkpointing的控制上面我们了解到整个流上面我们会随着时间推移不断的做Checkpointing , 不断的产生snapshot存储到Statebackend中 , 那么多久进行一次Checkpointing?对产生的snapshot如何持久化的呢?带着这些疑问 , 我们看看Flink对于Checkpointing如何控制的?有哪些可配置的参数:
  • checkpointMode - 检查点模式 AT_LEAST_ONCE 或 EXACTLY_ONCE
  • checkpointInterval - 检查点时间间隔 , 单位是毫秒
  • checkpointTimeout - 检查点超时时间 ,单位毫秒
如何做到exactly-once上面内容我们了解了Flink中exactly-once和at-least-once只是在进行checkpointing时候的配置模式 , 两种模式下进行checkpointing的原理是一致的 , 那么在实现上有什么本质区别呢?
语义从语义上面exactly-once 比 at-least-once对数据处理的要求很严格 , 更精准 , 那么更高的要求就意味着更高的代价 , 这里的代价就是 延迟 。
  • at-least-once - 语义是指流上所有数据至少被处理过一次(不要丢数据)
  • exactly-once - 语义是指流上所有数据必须被处理且只能处理一次(不丢数据 , 且不能重复)
实现那在实现上面Flink中at-least-once 和 exactly-once有什么区别呢?区别体现在多路输入的时候(比如 Join) , 当所有输入的barrier没有完全到来的时候 , 早到来的event在exactly-once的情况会进行缓存(不进行处理) , 而at-least-once的模式下即使所有输入的barrier没有完全到来的时候 , 早到来的event也会进行处理 。 也就是说对于at-least-once模式下 , 对于下游节点而言 , 本来数据属于checkpoint n的数据在checkpoint n-1里面也可能处理过了 。
我以exactly-once为例说明exactly-once模式相对于at-least-once模式为啥会有更高的延时?如下图:
Flink中的Fault Tolerance 容错机制文章插图
上图示意了某个节点进行Checkpointing的过程:
  • 当Operator接收到某个上游发下来的barrier时候开始进行barrier的对齐阶段;
  • 在进行对齐期间barrier之后到来的input的数据会被缓存到buffer中;
  • 当Operator接收到上游所有barrier的时候 , 当前Operator会进行checkpointing , 生成snapshot并持久化;
  • 当checkpointing完成时候将barrier广播给下游operator;
当多路输入的barrier没有没有对齐时候 , barrier先到的输入数据会缓存在buffer中 , 不进行处理 , 这样对于下游而言buffer的数据越多就有更大的延迟 。 这个延时带来的好处就是相邻checkpointing所记录的数据(计算结果或event)没有重复 。 相对at-least-once模式数据不会被buffer , 减少延时的利好是以容忍数据重复计算为代价的 。
完整Flink任务Checkpointing过程在 《Apache Flink 漫谈系列 - State》中我们有过对Flink存储到State中的内容做过介绍 , 比如在connector会利用OperatorState记录读取位置offset , 那么一个完整的Blink任务的执行图是一个DAG , 上面我们描述了DAG中一个节点的过程 , 那么整体来看Checkpointing的过程是怎样的呢?在产生checkpoint并分布式持久到HDFS的过程是怎样的呢?
整体checkpoint流程
Flink中的Fault Tolerance 容错机制文章插图
上图我们看到一个完整的Flink任务进行Checkpointing的过程 , JM触发Soruce发射barriers,当某个Operator接收到上游发下来的barrier , 开始进行barrier的处理 , 整体根据DAG自上而下的逐个节点进行Checkpointing , 并持久化到Statebackend 。 一直到DAG的sink节点 。
Incremental checkpoint对于一个流计算的任务 , 数据会源源不断的流入 , 比如要进行双流JOIN , 由于两边的流event的到来有先后顺序问题 , 我们必须将left和right的数据都会在state中进行存储 , Left event流入会在Right的State进行join数据 , Right event流入会在LState中join数据 , 如下图左右两边的数据都会持久化到State中: