Flink的基本概念
Stream、Transformation、Operator
用户实现的Flink程序是由Stream和Transformation这两个基本构建块组成,其中Stream是一个中间结果数据,而Transformation是一个操作,它对一个或多个输入Stream进行计算处理,输出一个或多个结果Stream。在启动的时候从一个或多个Source Operator开始,结束于一个或多个Sink Operator。Flink 程序在运行的时候会被映射到数据流图中,这个数据流图就是由程序中的数据流和相应的变换操作组成的。数据流图开始于一个或多个数据源(source),结束于另外一些汇聚点(sink)。数据流图类似于有向无环图(DAG)。
下面是一个由Flink程序映射为Streaming Dataflow的示意图,如下所示:
Parallel Dataflow
在Flink中,程序天生是并行和分布式的:一个Stream可以被分成多个Stream分区(Stream Partitions),一个Operator可以被分成多个Operator Subtask,每一个Operator Subtask是在不同的线程中独立执行的。一个Operator的并行度,等于Operator Subtask的个数,一个Stream的并行度总是等于生成它的Operator的并行度。
有关Parallel Dataflow的实例,如下图所示:
上图Streaming Dataflow的并行视图中,展现了在两个Operator之间的Stream的两种模式:
-
- One-to-one模式
比如从Source[1]到map()[1],它保持了Source的分区特性(Partitioning)和分区内元素处理的有序性,也就是说map()[1]的Subtask看到数据流中记录的顺序,与Source[1]中看到的记录顺序是一致的。
-
- Redistribution模式
这种模式改变了输入数据流的分区,比如从map()[1]、map()[2]到keyBy()/window()/apply()[1]、keyBy()/window()/apply()[2],上游的Subtask向下游的多个不同的Subtask发送数据,改变了数据流的分区,这与实际应用所选择的Operator有关系。另外,Source Operator对应2个Subtask,所以并行度为2,而Sink Operator的Subtask只有1个,故而并行度为1。
Task、Operator Chain
在Flink分布式执行环境中,会将多个Operator Subtask串起来组成一个Operator Chain,实际上就是一个执行链,每个执行链会在TaskManager上一个独立的线程中执行,如下图所示:
上图中上半部分表示的是一个Operator Chain,多个Operator通过Stream连接,而每个Operator在运行时对应一个Task;图中下半部分是上半部分的一个并行版本,也就是对每一个Task都并行化为多个Subtask。
Window
Flink支持基于时间窗口操作,也支持基于数据的窗口操作。基于时间的窗口操作,在每个相同的时间间隔对Stream中的记录进行处理,通常各个时间间隔内的窗口操作处理的记录数不固定;而基于数据驱动的窗口操作,可以在Stream中选择固定数量的记录作为一个窗口,对该窗口中的记录进行处理。
Time
在处理Stream中的记录时,记录中通常会包含各种典型的时间字段,Flink支持多种时间的处理,如下图所示:
上图描述了在基于Flink的流处理系统中,各种不同的时间所处的位置和含义,其中,Event Time表示事件创建时间,Ingestion Time表示事件进入到Flink Dataflow的时间 ,Processing Time表示某个Operator对事件进行处理事的本地系统时间(是在TaskManager节点上)。Event Time是消息自带时间戳,当出现乱序的流时,Flink借鉴了Google的MillWheel项目,通过WaterMark来支持基于Event Time时间窗口,这样可以允许一些时间到达延迟,不至于影响窗口的计算。
WaterMark
WaterMark的工作机制如图:
WaterMark的含义是所有时间t'< t的事件都已经发生。WaterMark包含一个时间戳,并插入到stream中。并行数据流中,当Operator有多个输入流时,Operator的event time以最小流event time为准。Flink使用WaterMark标记所有小于该时间戳的消息都已流入,Flink的数据源在确认所有小于某个时间戳的消息都已输出到Flink流处理系统后,会生成一个包含该时间戳的WaterMark,插入到消息流中输出到Flink流处理系统中,Flink操作符按照时间窗口缓存所有流入的消息,当操作符处理到WaterMark时,它对所有小于该WaterMark时间戳的时间窗口的数据进行处理并发送到下一个操作符节点,然后也将WaterMark发送到下一个操作符节点。