checkpoint的过程包含了JobManager和Taskmanager端task的执行过程,按照步骤为:
1、在JobManager端构建ExecutionGraph过程中会创建CheckpointCoordinator,这是负责checkpoint的核心实现类,同时会给job添加一个监听器CheckpointCoordinatorDeActivator(只有设置了checkpoint才会注册这个监听器),在JobManager端开始进行任务调度的时候,会对job的状态进行转换,由CREATED转成RUNNING,job监听器CheckpointCoordinatorDeActivator就开始启动checkpoint的定时任务了,最终会调用CheckpointCoordinator.startCheckpointScheduler()
2、CheckpointCoordinator会部署一个定时任务,用于周期性的触发checkpoint,这个定时任务就是ScheduledTrigger,在触发checkpoint之前先做一遍检查,检查当前正在处理的checkpoint是否超过设置的最大并发checkpoint数量,检查checkpoint的间隔是否达到设置的两次checkpoint的时间间隔,在都没有问题的情况下向所有的source task去触发checkpoint,远程调用TaskManager的triggerCheckpoint()方法
3、TaskManager的triggerCheckpoint()方法首先获取到source task(即SourceStreamTask),调用Task.triggerCheckpointBarrier(),triggerCheckpointBarrier()会异步的去执行一个独立线程,这个线程来负责source task的checkpoint执行。checkpoint的核心实现在StreamTask.performCheckpoint()方法中,该方法主要有三个步骤
1)、在checkpoint之前做一些准备工作,通常情况下operator在这个阶段是不做什么操作的
2)、立即向下游广播CheckpointBarrier,以便使下游的task能够及时的接收到CheckpointBarrier也开始进行checkpoint的操作
3)、开始进行状态的快照,即checkpoint操作。
注意以上操作都是在同步代码块里进行的,获取到的这个lock锁就是用于checkpoint的锁,checkpoint线程和task任务线程用的是同一把锁,在进行performCheckpoint()时,task任务线程是不能够进行数据处理的
4、checkpoint的执行过程是一个异步的过程,保证不能因为checkpoint而影响了正常数据流的处理。StreamTask里的每个operator都会创建一个OperatorSnapshotFutures,OperatorSnapshotFutures 里包含了执行operator状态checkpoint的FutureTask,然后由另一个单独的线程异步的来执行这些operator的实际checkpoint操作,就是执行这些FutureTask。这个异步线程叫做AsyncCheckpointRunnable,checkpoint的执行就是将状态数据推送到远程的存储介质中比如hdfs或者rocksdb
5、对于非Source Task,checkpoint的标志性开始在接收到上游的CheckpointBarrier,方法在StreamTask中的CheckpointBarrierHandler.getNextNonBlocked()。CheckpointBarrierHandler会根据CheckpointingMode模式不同生成不同的Handler,如果是EXACTLY_ONCE,就会生成BarrierBuffer,会进行barrier对齐,保证数据的一致性,BarrierBuffer中的CachedBufferBlocker是用来缓存barrier对齐时从被阻塞channel接收到的数据。如果CheckpointingMode是AT_LEAST_ONCE,那就会生成BarrierTracker,不会进行barrier对齐,而是继续处理数据,在接收到上游task所有的CheckpointBarrier才开始进程checkpoint,这样就会checkpoint(n)的状态会包含checkpoint(n+1)的数据,数据不一致。非Source Task的checkpoint执行跟步骤3、4是一样的,只不过触发的线程是Task工作线程,跟source task不一样
6、Task在执行完checkpoint后会向JobManager上报checkpoint的元数据信息,JobManager端的CheckpointCoordinator会调用PendingCheckpoint.acknowledgeTask()方法,该方法就是将task上报的元数据信息(checkpoint的路径地址,状态数据大小等等)添加到PendingCheckpoint里
7、task的checkpoint会一直进行到sink task。JobManager如果接收到了全部task上报的的Ack消息,就执行completePendingCheckpoint(),会将checkpoint元数据信息进行持久化,然后通知所有的task进行commit操作,一般来说,task的commit操作其实不需要做什么,但是像那种TwoPhaseCommitSinkFunction,比如FlinkKafkaProducer就会进行一些事物的提交操作等,或者像FlinkKafkaConsumer会进行offset的提交
8、所有task执行完commit操作后(实际上执行的是operator.notifyCheckpointComplete()方法),一个完整的checkpoint流程就完成了
这里只是简单记录了总结,详细源码具体分析解读来自知乎的某位大佬 zhuanlan.zhihu.com/p/392556253