有状态的函数和操作需要存储关于计算的数据,这使得状态成为复杂计算的关键。在 Flink 中的每一种函数和操作都可以成为有状态的。为了达到很好的容错,Flink 的容错机制持续的记录分布式的数据流的快照。这些快照是非常轻量化的,因此高频的记录快照并不会影响性能。当进程由于机器,网络甚至是软件异常而失败的时候,Flink 会停止数据流。系统重启操作同时将他们恢复到最近的快照点。输入流也会被设置到记录快照点那个时间点。系统可以确保任何一条新于快照点的记录都不会记录在快照中,通俗点说就是一条记录不会存在于快照中同时还在数据流中等待被处理。
记录快照
Flink 容错机制的核心就是,记录分布式的数据流和状态的一致性快照。通过这些快照,系统可以从失败中恢复回来
屏障Barriers
A barrier separates the records in the data stream into the set of records that goes into the current snapshot, and the records that go into the next snapshot. 这些屏障将数据流分割成很多记录的集合。屏障自身非常轻量,不会影响数据流。
屏障被加入到流中的那一点 称为 Sn,就是一个快照会覆盖的数据截止位置。当快照 n 被认为完成,那么 Job 将永远不会向数据源去请求先于 Sn 的数据,因为即便任务失败,可以从快照 n 恢复,无需重新请求数据。
当一个操作对象接收多个流的情况下,需要按照以下逻辑,对输入流做对齐操作。
只有操作对象接收到屏障 n 便不在继续处理此输入流的数据,一直等到其它的输入流也收到屏障 n。否则不同批次快照数据会混合起来
属于快照 n 的数据流会被放入临时的 buffer 中
一旦最后一个流接收到屏障 n,操作对象开始发送全部缓存的数据,包括屏障 n 自身
最后,恢复接收并处理全部的输入的数据。处理 buffer 的数据优先于处理流中数据。
状态
当操作对象包含状态的时候,这些状态必须连同快照一并被记录下来。
操作对象接收到全部输入流的同一屏障后,会将自身状态记录下来。在这一点上,任何来自记录数据的更新都会生效,并且不在依赖这些记录数据。状态被记录后,操作对象确认记录的快照,然后会将快照屏障发送到输出流。
一个快照包括下面两点内容:
每一个输入流在记录快照时候的偏移量或者准确位置
一个操作对象的自身状态
恢复
恢复机制非常清晰明了,一旦失败发生,Flink 会选择最新的快照 k。系统会重新部署全部的数据流。将每一个操作对象的状态恢复为快照中记录的内容。数据源也会被重置到快照点的位置。
如果快照是增量式的。那么操作对象会恢复到最新的全量状态,然后开始应用一系列的增量快照的更新数据。