Flink架构和原理
现有的开源计算方案将流处理和批处理视为两种不同的应用类型,因为它们提供的SLA (service-level-aggregation)是完全不同的:流处理一般需要支持低延迟和一次性保证,而批处理需要支持高吞吐量和高效处理。
Flink从另一个角度看待流处理和批处理,并将它们统一起来:Flink完全支持流处理,即当看做流处理时,输入数据流是无界的;批处理被视为一个特殊的流,但是它的输入数据流被定义为有界的。
Flink流处理特性:
Flink以分层体系的形式组成其软件栈,不同层的栈基于其下层,每层接受程序不同层的抽象形式。
1.流、转换、运算符
Flink程序由Stream和Transformation两个基本构建块组成,其中Stream是中间结果数据,Transformation是一个运算,对一个或多个输入流进行计算和处理,输出一个或多个结果流。
当执行Flink程序时,它将被映射到流式数据流。流式数据流由一组流和转换运算符组成,类似于DAG图。在启动时,它以一个或多个源操作符开始,以一个或多个接收操作符结束。
2.并行数据流
一个流可以分成多个流分区,一个操作符可以分成多个操作符子任务,每个操作符子任务在不同的线程中独立执行。操作符的并行性等于操作符子任务的数量,而流的并行性总是等于生成它的操作符的并行性。
一对一模式
比如从Source[1]到map()[1],它保持了Source的分区特性和分区内元素处理的顺序,也就是说map()[1]的子任务看到的是数据流中记录的顺序,和Source[1]看到的是一样的。
再分配模式
这种模式改变了输入数据流的划分,比如从map()[1],map()[2]到key by()/window()/apply()[1],keyby ()/window ()/apply (2),以及上游子任务方向。
3.任务,运算符链
在Flink分布式执行环境中,多个操作符子任务会串在一起形成一个操作符链,实际上就是一个执行链,每个执行链都会在TaskManager上的一个独立线程中执行。
4.时间
在流中处理记录时,记录通常包含各种典型的时间字段:
事件时间:表示事件创建时间。
摄取时间:表示事件进入Flink数据流的时间。
处理时间:表示操作员处理事件时的当地系统时间。
Flink使用水印来测量时间的时间。水印携带时间戳t,并被插入到流中。
5.窗户
Flink支持基于时间的窗口操作和基于数据的窗口操作:
窗口分类:
翻转/滑动时间窗口
//流(sensorId,carCnt)
val vehicleCnts:数据流[(Int,Int)] =...
val tumbling CNTs:DataStream[(Int,Int)] = vehicleCnts
//按sensorId排列的密钥流
。密钥比(0)
//1分钟长度的翻转时间窗口
。time window(time . minutes(1))
//计算carCnt上的总和
。总和(1)
val slidingCnts: DataStream[(Int,Int)] = vehicleCnts
。密钥比(0)
//滑动时间窗口长度为1分钟,触发间隔为30秒
。timeWindow(时间.分钟(1),时间.秒(30))
。总和(1)
翻转/滑动计数窗口
//流(sensorId,carCnt)
val vehicleCnts:数据流[(Int,Int)] =...
val tumbling CNTs:DataStream[(Int,Int)] = vehicleCnts
//按sensorId排列的密钥流
。密钥比(0)
//100元素大小的滚动计数窗口
。计数窗口(100)
//计算carCnt总和
。总和(1)
val slidingCnts: DataStream[(Int,Int)] = vehicleCnts
。密钥比(0)
//滑动计数窗口的100个元素大小和10个元素触发间隔
。计数窗口(100,10)
。总和(1)
自定义窗口
基本操作:
6.容错
屏障机制:
对齐:
当操作员接收多个输入数据流时,数据流需要在快照屏障中对齐:
基于流对齐的操作可以实现恰好一次语义,但也会给流处理的应用带来延迟,因为为了对齐障碍,会在缓冲区中临时缓存一部分流记录,这在数据流并行度高的场景下可能更明显。通常,与障碍对齐的最新流被用作处理缓冲区中的缓存记录的时间点。在Flink中,提供了一个开关来选择是否使用流对齐。如果关闭,恰好一次将变成至少一次。
检查点:
快照既是数据流的一个检查点,也是操作者持有的一种状态,以保证在流处理系统出现故障时,数据流处理能够正确恢复。有两种状态:
7.行程安排
在JobManager端,将接收到客户端提交的JobGraph形式的Flink作业,JobManager会将JobGraph转换映射到ExecutionGraph,execution graph是JobGraph的并行表示,也就是说,实际的JobManager会调度一个作业在TaskManager上运行。
基于资源分配和使用的物理调度示例:
8.循环
机器学习和图形计算应用程序都将使用迭代计算。Flink通过在迭代算子中定义阶跃函数来实现迭代算法。这种迭代算法包括两种类型:迭代和增量迭代。
重复
Iterate算子是一种简单的迭代形式:每次迭代,阶跃函数的输入要么是整个数据集,要么是上一次迭代的结果,通过这次迭代计算出下一轮计算(也叫下一次部分解)所需的输入,在满足迭代终止条件后输出最终的迭代结果。
流程伪代码:
iteration state state = getInitialState();
而(!terminationCriterion()) {
state = step(状态);
}
setFinalState(状态);
增量迭代
Delta Iterate运算符实现增量迭代。
流程伪代码:
IterationState工作集= getInitialState();
iteration state solution = getInitialSolution();
而(!terminationCriterion()) {
(delta,工作集)= step(工作集,解);
solution.update(增量)
}
setFinalState(解决方案);
最小传播:
9.背压监控
在流处理系统中,当下游操作者跟不上处理速度时,如果下游操作者能够将其处理状态传播给上游操作者,减缓上游操作者的处理速度,上述问题就会得到缓解,比如通过报警的方式将问题告知现有的流处理系统。
Flink Web接口提供了对正在运行的作业的背压行为的监控,这是通过使用采样线程对正在运行的任务进行堆栈跟踪采样来实现的。
默认情况下,JobManager将每隔50毫秒触发一次,依次对作业的每个任务进行100次堆栈跟踪调用。计算后得到一个比值,例如radio=0.01,这意味着100次中只有1次方法调用被阻塞。Flink目前定义了以下背压状态:
好的:0 & lt=比率& lt= 0.10
低:0.10 & lt;比率& lt= 0.5
高:0.5 & lt比率& lt= 1
1.桌子
Flink的Table API使用类SQL实现流和批处理。
详见:https://ci . Apache . org/projects/flick/flick-docs-release-1.2/dev/table _ api.html。
2.圆概率误差(circular error probable)
Flink的CEP(复杂事件处理)支持发现流中的复杂事件模式,快速过滤用户感兴趣的数据。
详见:https://ci . Apache . org/projects/flick/flick-docs-release-1.2/concepts/programming-model . html # next-steps。
3.葛里炸药
Gelly是由Flink提供的图形计算API,它提供了一个接口来简化图形计算和分析应用程序的开发和构建。
详见:https://ci . Apache . org/projects/flick/flick-docs-release-1.2/dev/libs/jelly/index . html。
4.FlinkML
FlinkML是Flink提供的机器学习库,提供可扩展的机器学习算法、简洁的API和工具,简化机器学习系统的开发。
详见:https://ci . Apache . org/projects/flick/flick-docs-release-1.2/dev/libs/ml/index . html。
明天更新部署和测试
本文仅代表个人观点。如果阐述得不好,请指导我改正。在这里我很感激。