原文链接
博主理解篇
Flink提供不同级别的抽象来开发流/批处理应用程序。
低阶的处理函数集成了DataStream API,这样就可以针对特性的操作使用低层级的抽象。DataSet API 为有边界的 data sets提供了附加的原语,例如循环/迭代。
Flink程序的基本构建模块是streams(流)和transformations(转换)。(需要注意的是,Flink的DataSet API所使用的DataSets内部也是流-更多内容将在以后解释)。从概念上讲流(可能没有结束)是一个数据流记录,而转换是一个操作,它取一种或者多个流作为输入,并产生一个或者多个输出流作为结果。
当执行的时候,Flink程序映射到streaming dataflows(流数据流),由streams和转换operators组成。每一个数据流开始于一个或者多个source,并且终止于一个或者多个sink。数据流类似于任意的有向无环图(DAGS)。虽然通过迭代构造允许特定形式的环,但是大多数情况下,简单起见,我们都不考虑这一点。
通常情况下,程序中的转换与数据流中的操作是一一对应的。有时,然而,一个转换可能有多个转换操作构成。
source和sink的文档在streaming connectors和 batch connectors 。Transformation的文档在DataStream operators和DataSet transformation。
Flink程序本质上是并行的和分布式的。在执行过程中,一个流(stream)包含一个或多个流分区 (stream partition),而每一个operator包含一个或多个operator子任务 。操作子任务之间彼此独立,在不同的线程中执行,甚至有可能运行在不同的机器或容器上。
operator子任务的数量即是此特定operator的并行度 。一个流的并行度即其生产operator的并行度。相同程序中的不同的operator可能有不同级别的并行度。
流在两个operator之间传输数据,可以通过一对一(或称 forwarding )模式,或者通过redistributing模式:
聚合事件(比如计数、求和)在流上的工作方式与批处理不同。比如,对流中的所有元素进行计数是不可能的,因为通常流是无限的(无边界的)。相反,流上的聚合需要由窗口来划定范围,比如 “计算过去的5分钟” ,或者 “最后100个元素的和” 。
窗口可以是事件驱动的 (比如:每30秒)或者数据驱动的 (比如:每100个元素)。窗口通常被区分为不同的类型,比如滚动窗口 (没有重叠), 滑动窗口 (有重叠),以及会话窗口(由不活动的间隙所打断)
更多的窗口例子可以查看这个博客。更多的明细可以查看窗口文档window docs。
当提到流程序(例如定义窗口)中的时间时,你可以参考不同的时间概念:
尽管数据流中的很多操作一次只查看一个独立的事件(比如事件解析器),有些操作却会记录多个事件间的信息(比如窗口算子)。 这些操作被称为有状态的 。
有状态操作的状态保存在一个可被视作嵌入式键/值存储的部分中。状态由有状态operator读取的流一起被严格地分区与分布。因此,只能访问一个 keyBy() 函数之后的 keyed streams 的键/值状态,并且仅限于与当前事件键相关联的值。调整流和状态的键确保了所有状态更新都是本地操作,以在没有事务开销的情况下确保一致性。这种对齐还使得Flink可以透明地重新分配状态与调整流的分区。
查看更多信息,请查看此文档有关state的内容。
Flink使用流重放与检查点的结合实现了容错。检查点与每个输入流的特定点及与相关的每一个operator的状态相关。一个数据流可以从一个检查点恢复出来,其中通过恢复operator状态并从检查点重放事件以保持一致性 (一次处理语义)
检查点间隔是以恢复时间(需要重放的事件数量)来消除执行过程中容错的开销的一种手段。
容错内部的描述提供了更多关于flink管理检查点和相关的话题。启用和配置检查点的详细信息请查看这个文档checkpointing API docs。
Flink将批处理程序作为流处理程序的特殊情况来执行,只是流是有界的(有限个元素)。 DataSet 内部被视为数据流。上述适用于流处理程序的概念同样适用于批处理程序,除了一些例外:
原文链接
对于分布式运行,Flink将operator子任务链接在一起放入任务池。每个任务由一个线程执行。将operator链接到任务池中是一项有用的优化:它减少线程到线程的切换和缓冲的开销,并在降低延迟的同时提高整体吞吐量。可以配置链接行为,有关详细信息,请查阅链接文档。
下图中的示例数据流由五个子任务执行,因此有五个并行线程。
Flink运行时有两种类型的进程组成:
每个Worker节点(任务管理器)是一个JVM进程,在分开的线程中可以执行一个或多个子任务。一个Worker通过控制task slots(至少一个)来控制节点接受多少任务。
每个task slot代表任务管理器固定大小的资源子集。例如:一个拥有3个slot的任务管理器,将会分配它管理的1/3内存到每个slot。对资源进行分槽(slot)意味着子任务不会与其他作业的子任务竞争管理的内存,而是具有一定数量的保留管理内存。注意此处没有CPU隔离发生,现在只能分隔任务的管理内存。
通过调整task slot数目,用户可以定义子任务之间如何隔离。每个任务管理器拥有一个slot意味着任务组运行在隔离的JVM(例如,可以在隔离的容器上启动)上。拥有多个slots意味着更多的子任务共享相同的JVM。在相同的JVM上的任务共享TCP连接(通过多路复用)和心跳信息。它们还可以共享数据集和数据结构,从而减少每个任务的开销。
默认情况下,Flink允许子任务共享slot,即使它们是不同任务的子任务,只要它们来自同一个作业。结果就是一个slot拥有这个作业的所有管道操作(pipeline)。允许这种slot共享有两个主要的好处:
存储键/值对索引的确切数据结构取决于所选的状态后端。一个状态后端将数据存储在内存中的哈希映射中,另一个状态后端使用[RocksDB]()作为键/值对存储。除了定义保存状态的数据结构之外,状态后端还实现逻辑以获取键/值对状态的时间点快照,并将该快照存储为检查点的一部分。
用Data Stream API编写的程序可以从保存点恢复执行。保存点允许更新程序和Flink集群,而不会丢失任何状态。
保存点是手动触发的检查点,它会获取程序的快照并将其写入状态后端。他们依靠常规的检查点机制。在执行期间,程序会定期在工作节点上创建快照并生成检查点。对于恢复,仅仅需要最后完成的检查点,因此一旦新的检查点完成,就可以安全地丢弃旧的检查点。
保存点与这些定期检查点类似,不同之处在于它们由用户触发,并且在较新的检查点完成时不会自动过期。可以从命令行或通过REST API取消作业时创建保存点。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。