一,抽象层次数据库
Flink提供不一样级别的抽象来开发流/批处理应用程序。编程
1,stateful streamingwindows
最底层。它经过Process Function嵌入到DataStream API中。它容许用户从一个或多个流自由处理事件,并使用一致的容错状态。此外,用户能够注册事件时间和处理时间回调,容许程序实现复杂的计算。后端
2,Core APIs缓存
实际上,大多数应用程序不须要上述的低级别抽象,而是针对Core API(如DataStream API(有界/无界流))和DataSet API(有界数据集)进行编程。这些流畅的API为数据处理提供了常见的构建模块,如用户指定的各类转换形式,链接,聚合,窗口,状态等。在这些API中处理的数据类型以各自的编程语言表示为classes。底层的Process Function和DataStream API的整合,使得针对一些特定的操做能够实现更低层次的抽象。DataSet API为有界数据集提供了额外的原函数,如循环/迭代。安全
3,Table API微信
Table API是以表为中心的声明式DSL,多是动态更改表(表示流时)。Table API遵循(扩展)关系模型:Table 具备附加schema(与关系数据库中的表类似),API提供操做,例如select,project,join,group-by,aggregate等。Table API表明的是应该作什么逻辑操做,而不是直接指定如何编写操做的源代码。虽然Table API能够经过各类类型的用户定义的函数进行扩展,但它不如Core API那么具备表达力,但使用起来更加简洁(少写不少代码)。数据结构
此外,Table API程序还能够经过在执行以前应用优化规则的优化器。并发
能够在表和DataStream / DataSet之间无缝转换,容许程序将Table API和DataStream和DataSet API混合使用。框架
4,SQL
最高层次的抽象就是SQL。不管是语法仍是表达,该层次的抽象都很像Table API。SQL抽象与Table API紧密交互,SQL查询能够在Table API中定义的表上执行。
二,Programs and Dataflows
Flink程序的基本构建块是流和转换。在概念上,stream 是data records的(潜在的永无止境的)flow,而且变换是将一个或多个流做为输入的操做,而且做为结果产生一个或多个输出流。
执行时,Flink程序被映射成streaming dataflows,由streams 和转换操做符组成。每一个dataflow 从一个或多个sources开始,并以一个或多个sinks结束。dataflows 像任意的有向无环图(DAG)。虽然经过迭代构造容许特殊形式的循环,可是为了简单起见,咱们大部分都会任务是DAG。
一般,程序中的变换和数据流中的运算符之间存在一对一的对应关系。然而,有时,一个变换可能由多个转换算子组成。
三,Parallel Dataflows
Flink中的程序本质上是并行和分发的。在执行期间,流具备一个或多个流分区,而且每一个运算符具备一个或多个运算符subtask。操做符subtask彼此独立,并以不一样的线程执行,可能在不一样的机器或容器上执行。
运算符子任务的数量是该特定操做符的并行性。stream 的并行性老是其生产运算符的并行性。同一程序的不一样运算符可能具备不一样的并行级别。
Streams 能够以一对一(或转发)模式或从新分配模式在两个运算符之间传输数据:
1),一对一
One-to-one streams(例如上图中的Source和map()运算符之间)保留元素的分区和ordering。这意味着map()运算符的子任务[1]看到的元素的顺序将和由Source 操做符产生的顺序相同。
2),再分配
从新分配流(如map()和上面的keyBy / window之间以及keyBy / window和Sink之间)改变流的分区。每一个操做符子任务根据所选择的转换将数据发送到不一样的目标子任务。
KeyBy是按照key的hash值进行从新分区,rebalance()是以随机的方式从新分区。在从新分配交换中,元素之间的排序仅保留在每对发送和接收子任务对(例如,keyBy / window的map()和子任务[2]的子任务[1]中)。上例子中仅保证相同key的元素顺序性。
四,Windows
Aggregating events(例如,counts,sums)在流上的工做方式与批处理不一样。例如,不可能对流中的全部元素进行计数,由于流一般是无限的(无界)。相反,流上的聚合(计数,总和等)由窗口限定,例如“最后5分钟计数”或“最后100个元素的总和”。
Windows能够时间驱动(例如:每30秒)或数据驱动(例如:每100个元素)。一般区分不一样类型的窗口,例如翻转窗口(无重叠)[tumbling windows (no overlap)],滑动窗口(具备重叠)[sliding windows (with overlap)]和会话窗口(由不活动空隙划分)[ession windows (punctuated by a gap of inactivity)]。
五,Time
当在Streaming 程序中使用时间的时候,如定义窗口时,能够参考不一样的时间概念:
1,Event Time
Event Time是Event建立的时间。Events中的Event Time是以时间戳的格式存在。Fink经过timestamp assigners来得到event timestamps。timestamp assigners后面出文章具体说。
2,Ingestion time
Ingestion time是event进入flink dataflow的时间。
3,Processing Time
Processing Time是基于时间的操做算子执行的本地时间。
六,Stateful Operations
虽然dataflow 中的许多操做只是一次处理一个单独的事件(例如事件解析器),但一些操做会记住跨多个事件的信息(例如窗口运算符)。这些操做称为有状态。有状态的操做算子,状态保存在嵌入式的键/值存储中。状态会和被状态操做算子读取的streams一块儿分区和分配。使用keyBy函数后,仅keyed streams可能获取key/value状态,而且仅限于与当前事件key相关的值。对齐stream和state的keys,确保全部状态更新都是本地操做,保证一致性,无需事务开销。此对齐还容许Flink从新分配状态并透明地调整流分区。
七,Checkpoints
Flink使用stream replay和checkpoint组合来实现容错。检查点与每一个输入流中的特定点相关联,以及每一个运算符的相应状态。Streaming dataflow能够从检查点恢复流,同时经过恢复操做符的状态,从检查点从新执行事件来保持一致性(一次性处理语义)。
检查点间隔是在恢复时间(须要从新计算的事件数)的状况下,在执行期间消除容错的开销的一种手段。
八,Batch on Streaming
Flink执行批处理程序做为流程序的特殊状况,其中streams 是有限的(有限数量的元素)。DataSet在内部被视为数据流。以上概念所以适用于批处理程序,一样适用于流式传输程序,但有一些例外:
1,批处理程序的容错不使用checkpoint。恢复须要彻底执行流。这是可能的,由于输入是有限的。恢复成本增长,可是使得处理变得廉价,由于无需进行checkpoint。
2,DataSet API中的有状态操做使用简化的in-memory/out-of-core数据结构,而不是键/值索引。
3,DataSet API引入了特殊的同步(superstep-based)迭代,这些迭代只能在有界流上进行。具体后面出文章介绍。
九,Tasks and Operator Chains
为了分布式执行,Flink 链式合并operator subtasks成tasks。每一个task被一个线程执行。链式的将操做符合并成任务是一个颇有用的优化:它减小了线程到线程切换和缓冲的开销,而且在减小延迟的同时增长了整体吞吐量。链式操做是能够配置的(后面出文章具体介绍)。
下图dataflow的例子,使用五个subtasks执行,因而须要五个并发线程。
十,flink的角色
Flink运行时由两种类型的进程组成:
1),JobManager也叫master协调分布式执行。他们调度任务,协调checkpoints,协调故障恢复等。至少有一个JobManager。高可用状况下能够启动多个JobManager,其中一个选举为leader,其他为standby。
2),TaskManager也叫worker,负责执行具体的tasks。缓存,交换数据流。至少有一个TaskManager。
JobManager和TaskManager能够用不少种方式启动:能够直接做为Standalone集群启动,也能够被yarn或者Mesos管理。TaskManager链接到JobManager,宣布本身可用,并接受分配的工做。
客户端不是runtime 和程序执行的一部分,而是用于准备并发送数据流到JobManager。
以后,客户端能够断开链接或保持链接以接收进度报告。客户端做为触发执行的Java / Scala程序的一部分运行,或在命令行进程中运行./bin/flink运行。。
十一,Task Slots and Resources
每一个worker(或者叫TaskManager)是一个jvm进程,能够在独立的线程中执行一个或者多个subtasks。为了控制worker接受tasks数,worker称之为任务槽数(至少有一个)。
每一个task slot表明TaskManager的一个固定部分资源。例如,一个TaskManager有三个slot,会均分其管理的内存给每一个slot。按槽分配资源意味着一个subtask不会与其它job的subtask竞争管理的内存,而是使用保留的内存资源。这里并无实现cpu资源的隔离。仅仅实现了基于内存的资源隔离。
经过调整task slots的数量,用户能够定义子任务彼此隔离的方式。每一个TaskManager拥有一个slot 意味着每一个任务组在单独的JVM中运行(例如,能够在单独的容器中启动)。拥有多个slots 意味着更多的子任务共享相同的JVM。相同JVM中的任务共享TCP链接(经过复用)和心跳消息。他们还能够共享数据集和数据结构,从而减小每一个任务的开销。
默认状况下,Flink容许子任务共享slot,即便它们是不一样tasks的subtasks,只要它们来自相同的job。结果是一个slot能够处理整个job pipeline。容许这个slot共享有两个主要好处:
1),Flink集群须要与job中使用的最高并行度彻底相同的task slot数。不须要计算一个程序总共包含多少任务(具备不一样的并行性)。
2),更容易得到更好的资源利用率。没有slot共享,非密集的source / map()子任务将拥有与资源密集型窗口子任务同样多的资源。使用slot共享,经过将例子中国的基础并行度从2增长到6,能够充分利用slot资源,同时保证heavy subtasks均匀的分配到不一样taskmanager中。
也有resource 组机制,能够组织不但愿的slot共享。
做为经验法则,task slot最佳默认数量将是CPU内核的数量。
十二,State Backends
key/values索引存储的确切数据结构取决于所选的State Backends(目前有三种:MemoryStateBackend,FsStateBackend,RocksDBStateBackend)。一种state backend将数据存储于内存的hash map中,另外一种state backend使用的是RocksDB,还有就是使用文件。除了定义保存状态的数据结构以外,state backends 还实现逻辑以获取键/值状态的 point-in-time 快照,并将该快照存储为checkpoint的一部分。
十三,Savepoints
使用Data Stream API编写的程序能够从Savepoints恢复执行。Savepoints容许更新程序和Flink集群,而不会丢失任何状态。
Savepoints 是手动触发的checkpoints,它们记录程序的快照并将其写入状态后端。他们依靠这个常规的检查点机制。执行过程当中,按期在工做节点上快照并生成检查点。为了恢复,只须要最后完成的检查点,一旦新的检查点完成,能够安全地丢弃较旧的检查点。Savepoints 与这些按期checkpoints相似,除了它们由用户触发,而且在较新的检查点完成时不会自动过时。能够从命令行建立保存点,也能够经过REST API取消做业。
十四,总结
Flink做为一个流式处理的框架,在实时计算中也是很常见的。Flink应用程序总共有如下三个部分:
1),Data source:Flink处理的输入数据
2),Transformations:Flink修改传入数据时的处理步骤
3),Data sink: flink处理结束后输出位置
kafka,hbase,spark等源码入门到深刻,spark机器学习,大数据安全,大数据运维,请关注浪尖公众号,看高质量文章。
本文分享自微信公众号 - 浪尖聊大数据(bigdatatip)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。