Flink系列之Flink中Checkpoint容错机制

1,669 阅读7分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第31天,点击查看活动详情

Flink中Checkpoint容错机制1

三、Flink Checkpoint 容错机制原理概述

Flink 提供了 Exactly once 特性,是依赖于带有 barrier 的分布式快照 + 可部分重发的数据源功能实现的。而分布式快照中,就保存了 operator 的状态信息。

Flink 的失败恢复依赖于 检查点机制 + 可部分重发的数据源。

  • 一、检查点机制:Checkpoint 定期触发,产生快照,快照中记录了:
  1. 当前检查点开始时数据源(例如 Kafka)中消息的 offset。
  2. 记录了所有有状态的 Operator 当前的状态信息(例如 sum 中的数值)。(Application/Job Operator / / Task
  3. 通俗的解释:每隔一段时间,就给这个 job 中的所有 Task 的state 做一次持久化,所以所有 Task State 的持久化成功了,则意味着这个 job 在这个时刻的 checkpoint 就成功了, 也就意味着给这个 job 在当前时刻做了一次 checkpoint
  • 二、可部分重发的数据源:Flink 选择最近成功完成的检查点,然后系统重放整个分布式的数据流,然后给予每个 Operator 他们在该检查点快照中的状态。数据源被设置为从合适位置开始重新读取流。例如在 Apache Kafka 中,那意味着告诉消费者从偏移量 offset 开始重新消费。
  1. 通俗的解释:我从你哪儿拉取一部分数据执行消费,数据拉取成功了,但是消费失败。 我要重来一次。那到底从那个地方继续呢?

(1)如果数据源具备数据重放功能:那么没有消费处理成功的数据,就再拉取处理一次

(2)如果数据源不具备数据重放功能: 失败之后就再也拿不到之前拉取的数据了。数据丢失了

分布式消息系统:kafak rocketmq 都是具备数据重放能力的组件。

探讨一个问题:现在让你实现 Flink 的检查点机制的 功能,该怎么做?

图零 整体的:CheckPoint简单设计

Flink之Checkpoint 的简单设计.png 图一:当任务失败的时候

当任务运行失败的时候:

Flink之Checkpoint全流程分析01任务运行失败.png 拍摄快照的时候,有两种结果是可以接受的:

如果标记放在 7 的后面: offset =7, sum_odd = 16, sum_even = 12    
如果标记放在 6 的后面: offset =6, sum_odd = 9, sum_even = 12
如果标记放在 5 的后面: offset =5, sum_odd = 9, sum_even = 6

如果直接把上图中的每个 Task 的状态直接保存,那么就是不合理的(有些数据,上游已经处理了,但是下游没有被处理):

offset =7, sum_odd = 9, sum_even = 12 XXXXXXXXXXXX, 如果 job 从这个状态中执行恢复,则 offset = 7 的这条数据就丢失了,没有参与计算

就一个需求:需要保证每一条数据,都完整的通过了这条处理链路(Source ---> Transform ----> Sink)

然后我们重启应用,对应的状态数据已经丢失了。

图二:重启应用

Flink之Checkpoint全流程分析02重启 Application.png 图三:CheckPoint恢复数据

Flink应用程序从checkpoint恢复数据:

Flink之Checkpoint全流程分析03从 Checkpoint 恢复状态.png 图四:Flink应用程序继续运行

Flink应用程序继续运行:

Flink之Checkpoint全流程分析04Application 继续运行.png

四、Flink CheckPoint 算法原理深入剖析

State 是管理一个 Task 的状态,那么一个 Flink Job 在运行过程中,是由很多的 Task 分布式并行运行组成的。保管和管理一个 Task 的状态,对于一个 Task 的容错来说,非常重要,同样,保存和管理这个 Job 的所有 Task 的状态,并保持一致,也同样非常重要。这是 Flink 的 Job 容错的最终解决方案。

Flink 容错机制的核心是对数据流做连续的分布式快照(snapshots),我们把每一次 take snapshot 动作称之为 Checkpoint。Checkpoint 是 Flink 实现容错机制最核心的功能,它能够根据配置周期性地基于 Stream 中各个 Operator/Task 的状态来生成快照,从而将这些状态数据定期持久化存储下来,当 Flink 程序一旦意外崩溃时,重新运行程序时可以有选择地从这些快照进行恢复,从而修正因为故障带来的程序数据异常。

具体的概念(重要的总结):Flink 的 Checkpoint 机制基于 chandy-lamport 算法,在某一个时刻,对一个 Flink Job 的所有 Task 做一个快照拍摄(逻辑上解释),并且将快照保存在 内存/磁盘 中永久保存,这样子,如果 Flink Job 重启恢复,就可以从故障前最近一次的成功快照中进行状态恢复,从而实现保证 Flink 数据流式数据的一致性。当然,为了配合 Flink 能实现状态快照,并且 job 状态恢复,必须数据源具备数据回放功能。

简单地说,Checkpoint 是一种分布式快照:在某一时刻,对某个 Flink 作业所有的 Task 做一个快照(snapshot),并且将快照保存在 memory / filesystem 等存储系统中。这样,在任务进行故障恢复的时候,就可以还原到任务故障前最近一次检查点的状态,从而保证数据的一致性。当然,为了保证 exactly-once / at-leastonce 的特性,还需要数据源支持数据回放。

实现 Checkpoint 的核心是:Stream Barrier,它和普通消息无异,Stream barrier 作为一种标记信息插入到数据流和正常数据一起流动。barriers 永远不会超过记录,数据流严格有序,barrier 将数据流中的记录隔离成一系列的记录集合,并将一些集合中的数据加入到当前的快照中,而另一些数据加入到下一个快照中。每个 barrier 都带有快照的 ID,并且 barrier 之前的记录都进入了该快照。 barriers 不会中断流处理,非常轻量级。 来自不同快照的多个 barrier 可以同时在流中出现,这意味着多个快照可能并发地发生。

Flink 应用程序中的消息抽象其实是:BufferOrEvent(DataStream 数据流中的每条 记录 的数据抽象对象),它包含两个方面的信息:

01、Buffer:正常的待处理的数据
02、Event:嵌入到数据流中增强引擎流处理能力的特殊消息,包含 CheckpointBarrier 和 WaterMark
03、一个 DataStream 数据流中的数据其实有多种类型: data,checkpointbarrier,watermark

Flink 的 Checkpoint Coordinator 在需要触发检查点的时候要求数据源向数据流中注入 Stream Barrier(具体实现: CheckpointBarrier(checkpointID,timestamp)),当执行 Task 的 Operator 从他所有的 InputChannel 中都收到了 Stream Barrier 则会触发当前的 Operator 的快照拍摄,并向其下游 Operator发送 Stream Barrier。当所有的 SinkOperator 都反馈完成了快照之后, Flink Checkpoint Coordinator 认为 Checkpoint 创建成功。

为了方便大家清楚理解 Checkpoint 的工作机制,在此提供了三张图:

图一:

官方图之stream_barriers.svg

图二:

官方图之stream_aligning.svg 图三:

官方图之checkpointing.svg

为什么要做对齐?

目的是为了 确保 一条数据如果被一个 Operator/Task 消费,那么就一定要被所有 Operator/Task 消费。否则如果一条数据 被 上游Operator/Task 消费了,但是没有被下游 Operator/Task 消费,那么就会出现数据重复消费或者漏消费!



声明:
        文章中代码及相关语句为自己根据相应理解编写,文章中出现的相关图片为自己实践中的截图和相关技术对应的图片,若有相关异议,请联系删除。感谢。转载请注明出处,感谢。

        落叶飘雪