开发者学堂课程【开源 Flink 极客训练营:Fault-tolerance in Flink】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/760/detail/13340
三.Flink的容错机制
1.流计算容错的一致性保证
容错,即恢复到出错前的状态。这里的“出错”包含多种可能的原因,比如由于网络问题导致的 worker 失联,意外导致的进程 crash,应用程序错误等等。
对于错误恢复,Flink 可以提供不同级别的一致性保证
Exactly once(严格一次)
每条 event 会且只会对 state 产生一次影响
注意:并非端到端的严格一次,Flink 内部的不包括 sink 处理
At least once(最少一次)
每条 event 会对 state 产生最少一次影响(存在重复处理)
At most once(最多一次)
每条 event 会对 state 产生最多一次影响,可能产生数据丢失。
注意:所有状态会在出错时丢失
端到端的 Exactly once
Exactly once:作业结果总是正确的,但是可能产出多次。处理完后结果写到 sink 里,因为故障要回滚。如果 sink 不支持回滚那么 sink 已经写出去。
端到端的 Exactly once:作业结果正确且只会被产出一次
Exactly once(&at least once)要求
-可重放的source
端到端的exactly once要求 除了可重放的source还需要
-事务型的sink,指标之前写入到 sink 的数据对于客户端是不可见的。
-可以接受幂等的产出结果
状态容错
要求 Exactly once 处理且仅处理一次,如何确保状态拥有 Exactly once 的容错保证?
2.简单场景的 exactly once 容错方法
记录本地的状态将 event log postition 记录下来。
比如当数据从源端的消息队列组到X位置,将状态 State@X记录下来,Y时将State@Y记录下来。
3.分布式场景的状态容错
确保状态拥有exactly once的容错保证首先对多个拥有本地状态的算子产生一个全局一致的快照,全局一致的快照对分布式进行容错。更重要的是,如何在不中断运算的前提下产生快照。
Flink 分布式场景的状态容错
4.Flink 作业拓扑:有向无环+弱联通图
不是 Flink 作业不支持有环的图,目前看到大部分 Flink 作业都是有向无环。可以使用裁剪的方法,裁剪的 Chandy-Lamport:记录所有输入的 offset,以及图中各节点的状态,依赖利用 rewindable source,可以回推的 source,卡盘的消息队列可以通过 channel state 读取早的时间点可是从新布局数据,增加一个依赖条件 rewindable source,可以不存储任意 channel state 存储,能节省的数据量非常大。计算逻辑中常用的是聚合逻辑,聚合逻辑输入多少消息处理之后只有一条 channel state 里可能有多条但在 operator state 里只有一条,能节省数据量。系统设计有 trade off增加的依赖 rewindable source。
容错恢复
将数据源的位置重新设定,每一个算子从检查点恢复状态,恢复完后退出到某一个时间点里的状态。
5.Flink 的分布式快照方法-Checkpoint barrier
元数据流里插入 Checkpoint barrier,是一种特殊的不同于银幕消息的特殊消息,在 Flink 里叫 Checkpoint barrier,不同 Checkpoint barrier 将流自然切分成了几个段,每段里包含 Checkpoint 数据。
Flink 的分布式快照方法-启动快照
Flink 里有全局的 Coordinator,不是任意进程都可发起快照。把 Checkpoint barrier 注入到每个 source 里,启动快照。
Flink 的分布式快照方法-收到 barrier 后
当每一个节点 barrier 后
-Source 保存其输入数据的 offsets
-算子(Operator)保存其 state
-事务型Sink节点对已有事务提交 pre-commit
Flink 的分布式快照方法-快照结束
每一个算子每一个并发按每一个 Checkpoint 后向 coordinator 发送确认消息,当所有的认为确认消息都被 Checkpoint 收到后,快照结束
快照流程示意图:
checkpoint barrier n 被注入到 Source 里,Source 将处理的分区 offset 记录下来。
随着时间的流逝将 checkpoint barrier 发到下游,下游有两个并发都去发 barrier,当 barrier 分别到达两个并发时,两个并发分别将状态记录到 checkpoint 里。图上画的同时但实际上两个 barrier 不一定同时到达。网络负载的情况与本地算子所在节点的运算能力是有关系的。
最后当 checkpoint barrier 达到最终的Source ,Operator状态也记录下来,完成拍照。
6.复杂场景-多流输入
当有多流输入时,做 Barrier 对齐。
Barrier 对齐流程-开始、对齐过程中、对齐完成触发快照、恢复数据处理
其中一条流 Barrier 到的到达后,另一条 Barrier 在管道中没有到达,将先到达的流在保证 exactly once 的情况下阻塞掉,等待另一条流数据处理,直到另一条流 Barrier 也到达后 unblock 之前的流同时将 Barrier 发送到算子。处理复杂流阻塞掉,流会发生反压。Flink 为了降低可能性有数据 buffer,buffer 满了后产生反压。
Barrier 对齐会导致反压,一方面看业务能不能执行降低 At-lease-once。
Exactly-once vs.At-least-once
如果不在对齐过程中阻塞已收到 barrier 的数据管道,会发生什么?
不阻塞数据1、2、3会流进来,1、2、3属于下一个 checkpoint 的数据但被包含在当前 checkpoint 里,恢复后由于 source 会回退,提前流入的数据会有重复的处理,数据就不再是 exactly-once 而是 at-least-once。
如果能接受 at-least-once,那么可以选择避免 barrier 对齐带来的副作用。
通过异步快照尽量减少任务停顿
本地快照时将本地快照的状态上传到分布式里本地的快照是同步上传到系统里的。
快照触发 stare copy-on-write
元数据信息做了快照后,数据处理恢复。这时上传数据过程中。
假设恢复的应用程序逻辑改了数据,不同的状态存储后端是不同的。如果是 Flink 用copy-on-write,如果是 RoscksDB 在 stateful 对本地进行快照,生产 DFS 键。
四.Flink 的状态管理
1.Flink 状态管理
首先定义状态,在例子里定义 value 状态,状态里加信息,状态识别 ID,然后给出状态数据类型信息 MyPojo,自定义的 Pojo 类型。向本地状态后端注册状态,在本地状态后端读写状态。
2.Flink 本地状态后端-JVM Heap
JVM Heap,本地的 Heap,本地的数据就是 Java 对象,读写以对象的方式所以非常快。有两个问题,对象的方式磁盘上压缩数据膨胀很多倍,通常大10倍,所以概念的空间很大。如果数据量大可能导致机械遇到问题。
读写时不需要形成序列化,形成 snapshot 时需要做序列化,异步的过程相对慢。快照做 checkpointed 时消耗增加很快。
3.Flink 本地状态后端-RocksDB
RocksDB 读写时需要做序列化,读写比 JVM Heap 慢很多。
RocksDB 快照时天生冷兼,在异步上传时冷兼的拷贝,消耗较低。
回顾:首先有状态的流计算,什么是流计算。一个无穷无尽的数据源、一个常驻本地的运算进程,进程里有几个逻辑一一处理数据源的数据。分布式流计算对流进行划分并处理。
流计算中的状态,处理一次事件是无状态的计算,事件之间有关联需要记录并且处理是有状态的计算。
状态有哪几种,去重、窗口统计、机器学习、历史数据的记录分析。
Flink 是一个分布式系统,介绍分布式系统全局一致性快照。首先介绍概念什么是全局快照,全局快照几个部分,进程本地的状态,管道消息的状态。
什么是全局一致性快照,如果两个事件先后发生,后面发生事件包含在快照里,那么前面事件也被包含在快照里。满足此条件是一致性快照。
怎样做全局一致性快照,使用时钟同步,有时间偏差,性能损失太大Stop-the-world。需要异步快照,快照过程中不影响消息的收发和应用进程的处理。Chandy-Lamport 算法背后小故事,两个教授吃饭想问题,Lamport 洗澡时想到算法跑到 Chandy 办公室,Chandy 在等他。Chandy-Lamport 算法流程怎样发起、怎样分布式进行、结束条件是什么。
全局一致性快照 Chandy-Lamport 算法与 Flink 快照区别,Chandy-Lamport 支持强连通图,而 Flink 面向弱连通图,Flink 的场景很多有向无环,依赖 rewindable source 规避管道消息的存储,聚合函数的存在,大大降低快照存储空间。
Flink 全局快照的流程与 Chandy-Lamport 非常像,Checkpoint barrier 对应 Chandy-Lamport 的 marker messages,快照过程有 Checkpoint coordinator 注入 barrier 触发快照,快照执行过程中 barrier 到达时每一个节点标记本地状态。结束条件由中控节点判断,所有节点本地快照做完成功为完整快照。举流程进行例子,如果是复杂场景、多流输入处理。
Flink 状态管理,除了全局一致性快照数据备份恢复外,本地存储两种选择,JVM Heap 速度很快,读写时不需要形成序列化,但空间膨胀力大,处理的状态数据量小,只能处理小数据量问题。RocksDB 数据量大,日常读写时需要做数据序列化,日常读写比 JVM Heap 慢很多。