TaskManager
ResourceManager
Dispacher
Yarn模式(Per-Job)运行流程
这里的ResourceManager是Yarn的ResourceManager
flink-conf.yaml
中的taskmanager.numberOfTaskSlots项目修改配置数量所有Flink程序都由三部分组成:Source、Transformation和Sink。
Source负责读取数据源,Transformation利用各种算子进行处理加工,Sink负责输出。
在运行时,Flink上运行的程序会被映射成“逻辑数据流”,它包含了以上的三个部分。
每个dataflow都以一个或多个source开始以一个或多个sink结束。dataflow类似于任意的有向无环图(DAG)。
大部分情况下,程序中的转换运算跟dataflow中的算子是一一对应关系。
Flink中的执行图可以分为四层:StreamGraph->JobGraph->ExecutionGraph->物理执行图
StreamGraph:是根据用户通过StreamAPI编写的代码生成的最初的图。用来标识程序的拓扑结构。
JobGraph:StreamGraph经过优化后生成了JobGraph,提交给JobManager的数据结构。主要优化为,将多个符合条件的节点chain在一起作为一个节点
ExecutionGraph:JobManager根据JobGraph生成ExecutionGraph。ExecutionGraph是JobGraph的并行化版本,是调度层最核心的数据结构。
物理执行图:JobManager根据ExecutionGraph对Job进行调度后,在各个TaskManager上部署Task后形成的“图”,并不是一个具体的数据结构
Flink采用了一种称为任务链的优化技术(类似于Spark的血缘关系),可以在特定条件下减少本地通信的开销。为了满足任务链的要求,必须将两个或多个算子设为相同的并行度,并通过本地转发(local forward)的方式进行连接
相同并行的的one-to-one操作,Flink这样相连的算子链接在一起形成一个task,原来的算子成为里面的subtask
并行度相同、并且是One-to-one操作,两个条件缺一不可
如果任务链中某项任务特别大,希望将其拆分的话,可以指定其中适当的算子调用disableChaining()
方法拆分(会被拆分为三个,前面部分、调用方法的算子、后面部分),调用该方法的算子前后部分会被分别放到不同的任务中
如果不想将某个算子单独切分出来,只想将任务前后切分,可以在切分位置后面的一个算子调用startNewChain()
方法,开启一个新的任务
slotSharingGroup("groupNameA")
方法可以指定该算子后之后算子的slot共享组,不设置共享组的话,所有算子默认在一个共享组中,这个共享组的名称为default
全局禁止任务链,使用env对象调用disableChaining()
方法
应用状态的一致性检查点是Flink故障恢复机制的核心,有状态流应用的一致检查点,起始就是所有任务的状态,在某个时间点的一份拷贝;这个时间点,应该是所有任务都恰好处理完一个相同的输入数据的时候
在执行流应用程序期间,Flink会定期保存状态的一致检查点,如果发生故障,Flink将会使用最近的检查点来一致恢复应用程序的状态,并重新启动处理流程,这种检查点的保存和恢复机制可以为应用程序状态提供“精确一次”(exactly-once)的一致性,因为所有算子都会保存检查点并恢复其所有状态,这样一来所有的输入流就都会被重置到检查点完成时的位置
Flink的检查点设置是一种基于Chandy-Lamport算法的分布式快照,可以将检查点的保存和数据处理分离开,不需要暂停整个应用
Flink的检查点算法用到了一种称为分界线(barrier)的特殊数据形式,用来把一条流上的数据按照不同的检查点分开
分界线之前到来的数据导致的状态更改,都会把包含在当前
分界线所属的检查点中;而基于分界线之后的数据导致的所有更改,都会被包含在之后
的检查点中
现在是一个有两个输出流的应用程序,用并行的两个source任务来读取、处理并写出数据
当达到设置的检查点保存间隔时间是,JobManager会向每个source任务发送一条带有新检查点ID的消息(图中三角形的消息),通过这种方式来启动检查点
当检查点消息传送到Source
时,Source Operator
将他们的状态写入检查点,并发出一个检查点barrier
状态后端在状态存入检查点之后,会返回通知给source任务,source任务会向JobManager确认检查点完成
数据源在保存状态的同时,后来的数据不能被处理,会被暂存起来,等待状态保存完成后处理
分界线对齐:检查点不同于普通消息,在re-distributed过程中并不是只发送某一个下游的Operator,而是通过广播的方式发送给下游所有的Operator,对于下游的Operator,只有所有上游发送的barrier都接收到,且barrier前面的数据均已处理过后,才可以开始保存检查点。
以下图为例,barrier向下游传递,sum任务会等待所有输入分区的barrier到达,才会去保存检查点。对于barrier已经到达的分区,继续到达的数据会被缓存,而barrier尚未到达的分区,数据会被正常处理。
这样做的目的是为了保证检查点保存信息时间的统一,防止上游数据在传往下游的过程中迟到。在下图中,Sum even算子收到了蓝色的检查点消息,则可认为本次检查点保存操作中Source 1的数据已经处理完成了,但是仍为收到Source 2的检查点消息,所以此时不能开始检查点保存操作。
当Operator收到所有输入分区的barrier(检查点消息)时,任务就将其状态保存到状态后端的检查点中,然后将barrier继续向下游转发
Sink任务保存完成后,也会向JobManager确认状态保存到checkpint完毕,当所有任务都确认已成功将状态保存到检查点时,检查点保存就真正完成了
/*开启check,可以调用空参,也可以传入一个毫秒数(时间间隔),如果不传入参数,默认值也是500,
还可以传入第三个参数,表示状态一致性的级别,默认exactly once*/
env.enableCheckpointing()
val conf = env.getCheckpointConfig //获取checkpoint配置,再通过配置对象调用set方法进行设置
conf.setCheckpointingMode(CheckpointingMode.AT_LEAST_ONCE) //设置一致性级别
conf.setCheckpointTimeout(60000L) //设置超时时间
conf.setMaxConcurrentCheckpoints(2)//运行同时并行多少个checkpoint,默认是1个
/*两次checkpoint之间最小间歇时间,即前面一次barrier完成到下一个barrier开始之间的最小间隔时间,
如果操作时间小于设置的最小间隔时间,下次操作将会被推迟直到满足要求,会覆盖掉并行设置*/
conf.setMinPauseBetweenCheckpoints(2000)
//设置是否更倾向于使用checkpoint恢复,如果savepoint比checkpoint更接近实际情况,则使用savepoint
conf.setPreferCheckpointForRecovery(true)
conf.setTolerableCheckpointFailureNumber(3)//设置容忍checkpoint失败次数
两种常用的重启策略
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,10000L))
env.setRestartStrategy(RestartStrategies.failureRateRestart(5,Time.of(5,TimeUnit.MINUTES),Time.of(10,TimeUnit.SECONDS)))
.uid(n)
方法手动设定版本号