这是我参与「第四届青训营 」笔记创作活动的第二天。
数据流是一个无限元组序列,不像SQL处理的表,是有界的,一次执行查询可以访问完整的数据。数据流的处理是将流转换成保存有状态的动态表,而动态表是随时间变化的,查询的结果会不断地更新。
那么,如果查询的过程中出现故障该怎么办呢?
这里首先要提到不同数据处理保证的语义:
At-most-once: 俗称“摆烂”,出现故障的时候,啥也不做。最多处理一次,这样带来的好处是降低延迟,提高速度。
At-least-once:出现故障的时候,能够保证至少一次,那么一条数据可能存在重复消费。有些操作是幂等操作,可以重复执行很多次,但只会导致一次结果更改,也就是说,后面再重复执行就不行作用了。这种情况下,At-least-once语义也就够用了。
Exactly-once:最严格的处理语义,每条数据只被逻辑处理过一次(指的是结果只改变过一次),从输出结果来看,仿佛故障从未发生。
那么,Flink内部是怎么实现Exactly-once的呢?
Checkpoint机制
当出现故障时,
第一步:重启应用。
此时所有的任务状态会清空。
第二部:读取之前的checkpoint,重置状态
第三步:继续运行。
那么,应该怎么设置checkpoint呢?
1. 暂停处理输入的数据;
2. 等待后续所有处理算子消费当前已经输入的数据;
3. 待步骤2结束后,作业所有算子复制自己的状态并保存到远端可靠存储;
还有就是,checkpoint该什么时候设置呢?也就是,应该什么时候存档呢?
最理想的情况下,那当然是每处理完一条数据就进行一个状态的保存。
可是这样毕竟太耗时耗资源了,Flink的默认策略是周期性的触发保存。
而关于设置checkpoint的细节,Flink是让所有任务都处理完同一条数据后保存,再做一份快照的保存,保证逻辑时间上的统一。