完美之道,不在无可增加,而在无可删减!
Flink提供了不同的数据处理抽象层来开发流、批处理应用。
低级处理函数集成了DataStream API,使得它可以在某些特定操作中进入低级抽象层。DataSet API在有限数据集上提供了额外的原语,比如循环/迭代(loops/iterations )。
Flink编程的基本模块是流streams和转换transformations,(注意:在Flink中DataSets使用DataSet API在本质上也是流处理,详细见后面)。概念上来说,流就是一个连续不断的数据记录流(没有终点),而一个转换transformation是把一个多个流作为输入并且处理产生一个或者多个输出流作为结果的一种操作。
在执行的时候,Flink程序被映射到数据流上去,持续的数据流和转换操作。每一个数据流有一个和多个源作为起点,终止于一个或多个接收器。数据流类似于一个有限无环图(DAGs ),虽然可以通过迭代结构来构造特殊的特殊形式的环路,但是大多数时候为了简化我们还是把它作为无环图来处理。
在程序的转换和数据流的操作之间通常是一对一的通信。 有时候一个转换操作也会由多个转换操作组成。
关于源和接收器在流连接器streaming connectors 和批处理连接器batch connectors 的文档中有说明。转换操作的说明在DataStream operators和DataSet transformations的文档中。
Flink的程序本身就是并行和分布式的。在执行时一个数据流有一个或多个数据流分块,并且每个操作有一个或者多个操作子任务。操作子任务是相互独立的,并且在不同的线程中执行,也有可能是在不同的机器或者容器中执行。
操作子任务的数量就是这个指定操作的并行度。流计算的并行度就是它自己的生产操作。相同程序的不同操作有可能有不同级别的并行度。
数据流可以一对一(或转发)的模式或者以重分配的模式在2个不同的操作间传输。
在数据流上进行聚合事件(比如,counts,sums)和批处理是不一样的。例如,在数据流上去计算所有的元素是不行的,因为数据流一般是无限制的(无界限)。取而代之在数据流上进行聚合是基于窗口的,比如“最后5分钟的计数”或者“对最后100个元素进行求和”。
窗口是可以时间驱动(例如:每30秒)或者数据驱动的(例如,每100个元素)。可以通过一些明显的特点要区别不同的窗口,例如翻滚窗口(没有重叠),滑动窗口(有重叠)和会话窗口( 不时会有一段不活跃的间隙)。
blog post有更多窗口示例,window docs这里有更详细的说明文档。
当提到数据流编程中的时间(例如定义窗口)的时候,我们可以参考下面不同的时间定义。
关于时间操作的更多详情看这里的文档事件时间文档event time docs.
虽然数据流中的许多操作一次只查看一个独立的事件(例如一个事件解析),有些操作在多个事件上会记录信息(例如窗口操作)。这类操作叫做带状态操作。
我们用可以认为是嵌入式的kv存储来维护状态类操作的状态。带状态操作读取数据流的状态,而数据流的这些状态被严格的分区并且被分发。因此, 因此,只有在keyBy()函数之后,才可以访问键/值状态,并且仅限于与当前事件的键相关联的值。对齐数据流key和状态,可以保证所有状态的更新都是本地操作,在不需要事务开销的情况下保证一致性。这种对齐同时也允许Flink透明的进行重新分发状态和数据流分块的调整。
更多信息,可以看这个文档state.
Flink用数据流回放和检查点的组合来实现容错。一个检查点和每一个输入数据流的特定点相关,以及和每个操作的对应状态。一个数据流处理可以从一个检查点恢复,同时通过从检查点的位置开始恢复操作状态和重播时间来保持一致性(精确一次的处理语义)。
检查点的间隔是一种方法,可以衡量在执行过程中容错的开销。(需要被回放事件的数量)
容错间隔的描述提供了更多关于Flink管理检查点和相关话题的资料。关于启用和配置检查点的详细信息都在这个文档中checkpointing API docs.
Flink以一种特殊的的流处理程序来执行批处理程序,这种批处理的数据流是有界数据流(有限梳理的元素)。一个DataSet被看作是一个有限的流数据集。上面的思路就是像流处理程序一样的处理批处理程序,只有少许例外。
可以在Flink的Distributed Runtime.分布式运行时一文中继续了解基本概念。
看完本文有收获?请分享给更多人
关注「黑光技术」加星标,关注大数据+微服务