Checkpoint机制详解 | 青训营笔记

236 阅读8分钟

这是我参与「第四届青训营 」笔记创作活动的第18天

背景

  • 在分布式计算系统中,为了保证数据的一致性需要对数据进行一致性快照。
  • Flink和Spark在做流式计算时,为了保证数据一致性都借鉴了Chandy-Lamport算法原理Chandy-Lamport算法目标是让多个分布式节点本地数据以及通信中的数据完成local snapshot本地状态保存最终能一起完成global snapshot保存全局状态
  • 只有了解分布式系统为了保证数据一致性的算法背景,才能更好理解Flink如何用Checkpoint来保证数据Exactly Once准确一次语义和何为barrier对齐。
  • 这篇文章就是对Chandy-Lamport算法核心思想以及Flink CheckPoint机制介绍。

2. Snapshot快照

2.1 快照介绍和作用

HDFS snapshot是HDFS整个文件系统,或者某个目录在某个时刻的镜像。该镜像并不会随着源目录的改变而进行动态的更新。可以将快照理解为拍照片时的那一瞬间的投影,过了那个时间之后,又会有新的一个投影。

HDFS快照的核心功能包括:数据恢复、数据备份、数据测试。

2.1.1 数据恢复

可以通过滚动的方式来对重要的目录进行创建snapshot的操作,这样在系统中就存在针对某个目录的多个快照版本。当用户误删除掉某个文件时,可以通过最新的snapshot来进行相关的恢复操作。

2.1.2 数据备份

可以使用snapshot来进行整个集群,或者某些目录、文件的备份。管理员以某个时刻的snapshot作为备份的起始结点,然后通过比较不同备份之间差异性,来进行增量备份。

2.1.3 数据测试

在某些重要数据上进行测试或者实验,可能会直接将原始的数据破坏掉。可以临时的为用户针对要操作的数据来创建一个snapshot,然后让用户在对应的snapshot上进行相关的实验和测试,从而避免对原始数据的破坏。

2.2 HDFS快照的实现

  • 在了解HDFS快照功能如何实现之前,首先有一个根本的原则需要记住:**快照不是数据的简单拷贝,快照只做差异的记录。**这一原则在其他很多系统的快照概念中都是适用的,比如磁盘快照,也是不保存真实数据的。因为不保存实际的数据,所以快照的生成往往非常迅速。
  • 在HDFS中,如果在其中一个目录比如/A下创建一个快照,则快照文件中将会存在与/A目录下完全一致的子目录文件结构以及相应的属性信息,通过命令也能看到快照里面具体的文件内容。但是这并不意味着快照已经对此数据进行完全的拷贝 。这里遵循一个原则:对于大多不变的数据,你所看到的数据其实是当前物理路径所指的内容,而发生变更的inode数据才会被快照额外拷贝,也就是所说的差异拷贝。
  • inode译成中文就是索引节点,它用来存放文件及目录的基本信息,包含时间、名称、拥有者、所在组等信息。
  • HDFS快照不会复制datanode中的块,只记录了块列表和文件大小。
  • HDFS快照不会对常规HDFS操作产生不利影响,修改记录按逆时针顺序进行,因此可以直接访问当前数据。通过从当前数据中减去修改来计算快照数据。

RDD

  • RDD(Resilient Distributed Datasets)[1] ,弹性分布式数据集, 是分布式内存的一个抽象概念,RDD提供了一种高度受限的共享内存模型,即RDD是只读的记录分区的集合,只能通过在其他RDD执行确定的转换操作(如map、join和group by)而创建,然而这些限制使得实现容错的开销很低
  • 对开发者而言,RDD可以看作是Spark的一个对象,它本身运行于内存中,如读文件是一个RDD,对文件计算是一个RDD,结果集也是一个RDD,不同的分片、 数据之间的依赖 、key-value类型的map数据都可以看做RDD。
  • Flink Checkpoint机制

Flink Checkpoint机制是Chandy-Lamport算法的一种变体,称为异步barrier快照。把生成CheckPoint的过程和处理过程分离,这样部分任务保存CheckPoint的过程中,其他任务还可以继续执行,来实现异步保存全局状态快照。

Flink整个系统主要由两个组件组成分别为JobManager和 TaskManager,Flink架构遵循 Master-Slave主从架构设计原则。JobManager为 Master节点, TaskManager为 Worker(Slave)节点有组件之间的通信都是借助于 Akka Framework,包括任务的状态以及 Checkpoint触发等信息。Checkpoint机制由JobManager Coordinator负责。

当Checkpoint Coordinator检查点协调器(JobManager的一部分)指示TaskManager触发Checkpoint检查点时,它会让所有数据流记录其偏移量,对Checkpoint barrier进行编号并插入其数据流中。更详细过程是这样的:

1)JobManager来向TaskManager内的数据源任务如Kafka Source触发检查点Checkpoint流程。

2)数据源算子Operator收到消息后,暂停发出记录(继续接收数据流先缓存),StateBackend状态后端触发生成本地状态快照Checkpoint检查点。

3)本地完成状态快照Checkpoint后,并把带有编号的Checkpoint Barrier广播到数据流分区即多并发的任务(传输给与数据源Source连接的其他算子Operator)。

4)StateBackend状态后端会在状态存为检查点完成后通知JobManager发送确认消息。

5)将所有栏栅Barrier发出后,数据源将恢复正常工作。

这些Barrier流过作业图,标示每个检查点Checkpoint之前和之后的部分流。

数据源任务发出的检查点Barrier栏栅分隔符会传输到与之相连的任务。检查点分隔符Barrier栏栅总是以广播形式发送,从而可确保每个任务能从它们的每个输入都收到一个Barrier栏栅分隔符。当任务收到一个新检查点Barrier栏栅分隔符时,会继续等待所有其他输入分区也发来这个检查点Barrier栏栅分隔符,如任务A完成当前批次编号checkpoint-100的Barrier前数据,但是其他任务还没完成checkpoint-100编号Barrier前的数据,这时任务A又收到checkpoint-101的Barrier前数据先缓存起来暂不处理,在等待过程中,它会继续处理那些从还未提供Barrier栏栅分隔符的分区发来的数据。对于已经提供分隔符的分区,它们新到来的记录会被缓冲起来,不能处理。这个等待所有分隔符到达的过程称为Barrier对齐。

Barrier对齐等待的是所有任务收到同一编号的Barrier栏栅分隔符,并每个任务完成Checkpoint检查点当前Barrier栏栅分隔符之前状态快照保存,才算完成整个分布式系统全局一致性快照保存。同一编号Barrier栏栅分隔符是JobManager定时触发的同一次Checkpoint状态快照机制生成的,Flink Checkpoint时间间隔默认10分钟触发一次。

当Job Graph中的每个算子Operator都收到其中之一Barrier栏栅时,它会记录其状态。具有两个输入流(如CoProcessFunction)的算子执行barrier栏栅对齐,以便快照snapshot将反映由于处理两个输入流中的事件直至(但不超过)两个barrier栏栅而生成的状态。

上述从开始对齐,结束对齐,检查点保存三幅图详细说明一下barrier对齐Checkpoint保存过程,现在如下约定上述数据流数字123456称为输入流A,数据流abcdefg称为输入流B;Checkpoint barrier为当前同一编号的barrier栏栅。

  • Begin alignment图:

此时输入流A的Checkpoint barrier已经到Operator即123,但输入流B的同一编号barrier在d和e中间,即Operator还没处理完输入流B的数据,就也没收到同一编号的barrier,那么Operator就要等待输入流B的barrier到来,这个过程叫等待对齐

  • End alignment图:

当Operator在等待数据流B的barrier时,同时也会继续收到数据记录123,先缓存起来不处理,因为123属于barrier左侧(即下一个编号barrier,不属于当前barrier)。当efg前(右侧)同一编号的barrier也到达Operator算子,等待对齐结束。

  • Checkpoint图:

  • Checkpoint图:

对齐结束了,开始做当前批次的Checkpoint状态快照保存,并输出当前编号barrier直到sink结束完成,并通知JobManager Coordinator当前批次Checkpoint完成。