说白了就是等你要处理的这个或这波数据被所有任务(执行完所有算子)处理完了 再做检查点保存(下图就是三个数据都被map、sum处理完 就做检查点保存 source是读取数据的)
下图只是一个检查点的保存过程(拆解)这一个检查点最终保存了三个数据的偏移量和状态
就比如几个小水杯(一个小水杯代表一个数据)往大水杯里倒水(就是保存状态)小水杯灌满,意味着这个数据被所有任务(也就是所有算子)处理完 才能往大水杯里倒水 所以当你小水杯灌水的时候 挂了 不影响大水杯 你小水杯都清空 回到大水杯上次保存的内容(上次检查点的时候)
详细步骤:
处理完前三个数据以后 做了一次检查点的保存 然后第四个第五个单词是flink和hello flink处理完 处理hello的时候挂了 如下图
就是小水杯(每条数据就是一个小水杯) 都处理好了 再倒入大水杯(保存检查点)如果某个小水杯寄了 小水杯都倒了 重来 恢复大水杯上一个状态即可
这里的意思是 在某一个数据后面紧放一个barrier 不管是source还是哪个算子 只有处理到barrier才会触发检查点的保存 这个barrier就是在数据流中不停地流 流到哪 哪里触发checkpoin, 你后面来的数据什么的正常来 正常处理 这样的话单一流是比较简单的 但是多个流的情况下就不好对齐:
可以看到 上面那个分区source处理hello、world、hello
source已经读到了三个单词 然后一个hello还没map
还有一个hello map了但是没统计sum(这是下面那个source来的hello)
下面只读取一个world(不是hello) 也在map后还没统计(都在路上...)
注意 这里所谓的持久化存储不是存储计算的结果 是先存储source的偏移量
下面那个barrier还没来 说明那个触发检查点的数据还没到
底下这段是关键:就这么理解:这里两个sum都是最后一个算子,sum只有收到了前面两个并行任务都送来的barrier才会触发checkpoint,不管用不用得到这个数据,实际上每个算子都会收到n个并行任务送来的n个barrier,所以只有这两个sum算子barrier相等了 也就是所谓对齐了 就可以持久化存储最终的计算结果了
背压(可以记忆为下游处理数据的速度跟不上产生数据的速度)
这样的话 因为一个barrier到了 但是另外一个分区的没到
也就是另外一个分区的数据还没到齐 就直接保存状态 不会出问题吗 不会 因为我们还保存了当前的上下文,缓冲区的数据
所以牺牲内存换低延迟