赞
踩
Apache Flink 是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。Flink 被设计为在所有常见的集群环境中运行,以内存速度和任何规模执行计算。
无界数据(Unbounded Data)
无界数据是指持续不断生成、没有明确结束点的数据流。这些数据流在时间上是无限的,可以一直产生新的数据。
特点:
例如:
电商网站上的用户点击流,可以无限期地生成点击事件,或者社交媒体上的实时消息流如朋友圈,微博等等。
有界数据(Bounded Data)
有界数据是指有限的、可以确定开始和结束的数据集。处理有界数据通常是批处理的典型特征。
特点:
例如:
一天的服务器日志文件,数据集是固定大小的,可以一次性处理或者过去一个月的销售数据,用于生成月度报告。
总结:
Apache Flink 擅长处理无界和有界数据集。精确的时间和状态控制使 Flink 的运行时能够在无界流上运行任何类型的应用程序。有界流由专门为固定大小数据集设计的算法和数据结构在内部处理,从而获得出色的性能。
数据流处理示例:
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<String> inputStream = env.socketTextStream("localhost", 9999);
DataStream<Tuple2<String, Integer>> wordCounts = inputStream
.flatMap(new Tokenizer())
.keyBy(0)
.timeWindow(Time.seconds(10))
.sum(1);
wordCounts.print();
env.execute("Stream WordCount");
批处理示例:
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
DataSet<String> text = env.readTextFile("input.txt");
DataSet<Tuple2<String, Integer>> wordCounts = text
.flatMap(new Tokenizer())
.groupBy(0)
.sum(1);
wordCounts.writeAsCsv("output.csv", "\n", " ");
env.execute("Batch WordCount");
总结:
数据流处理和批处理各有其应用场景和优势。数据流处理适用于实时性要求高、需要持续处理数据的场景,而批处理适用于数据量大、需要对完整数据集进行分析的场景。
不过市面上大部分使用Flink的情况来看,都是基于流数据处理的场景使用。
利用内存性能
有状态的 Flink 应用程序针对本地状态访问进行了优化。任务状态始终保存在内存中,如果状态大小超出可用内存,则保存在访问效率高的磁盘数据结构中。因此,任务通过访问本地(通常是内存中的)状态来执行所有计算,从而产生非常低的处理延迟。Flink 通过定期和异步地将本地状态检查点到持久存储来保证在发生故障时实现精确一次的状态一致性。
## 状态
每个重要的流式处理应用程序都是有状态的,也就是说,只有对单个事件进行转换的应用程序才不需要状态。任何运行基本业务逻辑的应用程序都需要记住事件或中间结果,以便在以后的某个时间点访问它们,例如在收到下一个事件时或在特定持续时间之后。
应用程序状态是 Flink 中的一等公民。通过查看 Flink 在状态处理上下文中提供的所有功能,您可以看到这一点。
时间
时间是流式应用程序的另一个重要组成部分。大多数事件流具有固有的时间语义,因为每个事件都是在特定时间点产生的。此外,许多常见的流计算都是基于时间的,例如窗口聚合、会话化、模式检测和基于时间的连接。流处理的一个重要方面是应用程序如何测量时间,即事件时间和处理时间之间的差异。
Flink 提供了丰富的时间相关功能。
分层
Flink 提供了三层 API,每层 API 在简洁性和表现力之间做了不同的权衡,并针对不同的用例。
Flink 是一款高输送量、低延迟的串流处理引擎。 Flink 应用程式由任意复杂的无环图资料流图组成,其中该图形包含串流和转换。资料从一个或多个资料来源撷取并传送到一个或多个目标。来源系统和目标系统可以是串流、讯息伫列或资料储存,包括档案、常用资料库和搜寻引擎。转换可以具有状态性,例如在时间段内进行的汇总或复杂的模式侦测。
透过两种不同的机制实现容错:以检查点自动和定期检查应用程式状态,将其复制到持久性储存中,以便在出现故障时自动复原;随需储存点,其中储存一致的执行状态映射,允许停止和恢复、更新或分流您的Flink 作业,在停止和重新启动后保留应用程式状态。检查点和储存点机制是非同步的,在不「停止世界转动」的情况下拍摄一致的状态快照,而应用程式则会继续处理事件。
事件驱动的应用程序是一种有状态的应用程序,它从一个或多个事件流中提取事件,并通过触发计算、状态更新或外部操作对传入事件做出反应。
事件驱动型应用程序是传统应用程序设计的演变,具有分离的计算层和数据存储层。在此架构中,应用程序从远程事务数据库读取数据并将数据保存到其中。
相比之下,事件驱动型应用程序基于有状态的流处理应用程序。在这种设计中,数据和计算位于同一位置,从而产生本地(内存或磁盘)数据访问。通过定期将检查点写入远程持久存储来实现容错。下图描述了传统应用程序架构与事件驱动型应用程序之间的区别。
事件驱动的应用程序有哪些优点?
事件驱动的应用程序无需查询远程数据库,而是可以在本地访问其数据,从而在吞吐量和延迟方面获得更好的性能。对远程持久存储的定期检查点可以是异步和增量的。因此,检查点对常规事件处理的影响非常小。但是,事件驱动的应用程序设计提供的好处不仅仅是本地数据访问。在分层架构中,多个应用程序共享同一个数据库是很常见的。因此,任何数据库更改(例如由于应用程序更新或扩展服务而更改数据布局)都需要进行协调。由于每个事件驱动的应用程序都负责自己的数据,因此更改数据表示或扩展应用程序所需的协调较少。
Flink 如何支持事件驱动的应用程序?
事件驱动应用程序的极限取决于流处理器处理时间和状态的能力。Flink 的许多出色功能都围绕这些概念展开。Flink 提供了一组丰富的状态原语,可以管理非常大的数据量(高达几 TB),并保证一次一致性。此外,Flink 对事件时间、高度可定制的窗口逻辑和细粒度的时间控制的支持使ProcessFunction高级业务逻辑的实现成为可能。此外,Flink 还具有一个复杂事件处理 (CEP) 库来检测数据流中的模式。
然而,Flink 对于事件驱动应用程序的突出功能是它对保存点的支持。保存点是一个一致的状态映像,可以用作兼容应用程序的起点。给定保存点,可以更新应用程序或调整其规模,或者可以启动应用程序的多个版本进行 A/B 测试。
分析作业从原始数据中提取信息和见解。传统上,分析是以对记录事件的有界数据集进行批量查询或应用的方式执行的。为了将最新数据纳入分析结果,必须将其添加到已分析的数据集中,然后重新运行查询或应用。结果将写入存储系统或作为报告发出。
借助复杂的流处理引擎,分析也可以实时进行。流式查询或应用程序不是读取有限的数据集,而是获取实时事件流,并在事件被使用时不断生成和更新结果。结果要么写入外部数据库,要么作为内部状态保存。仪表板应用程序可以从外部数据库读取最新结果,或者直接查询应用程序的内部状态。
Apache Flink 支持流式和批量分析应用程序,如下图所示。
流分析应用程序有哪些优势?
与批量分析相比,连续流式分析的优势不仅限于由于消除了定期导入和查询执行,从事件到洞察的延迟大大降低。与批量查询相比,流式查询不必处理输入数据中的人为边界,这些边界是由定期导入和输入的有界性质造成的。
另一方面是更简单的应用程序架构。批量分析管道由几个独立的组件组成,用于定期安排数据提取和查询执行。可靠地操作这样的管道并非易事,因为一个组件的故障会影响管道的后续步骤。相比之下,在 Flink 等复杂的流处理器上运行的流分析应用程序包含从数据提取到连续结果计算的所有步骤。因此,它可以依赖引擎的故障恢复机制。
Flink 如何支持数据分析应用程序?
Flink 为连续流和批量分析提供了非常好的支持。具体来说,它具有符合 ANSI 标准的 SQL 接口,具有统一的批处理和流式查询语义。无论是在记录事件的静态数据集上运行,还是在实时事件流上运行,SQL 查询都会计算相同的结果。对用户定义函数的丰富支持确保可以在 SQL 查询中执行自定义代码。如果需要更多自定义逻辑,Flink 的 DataStream API 或 DataSet API 可提供更多低级控制。
提取-转换-加载 (ETL) 是一种在存储系统之间转换和移动数据的常用方法。通常会定期触发 ETL 作业,以将数据从事务数据库系统复制到分析数据库或数据仓库。
数据管道的作用与 ETL 作业类似。它们转换和丰富数据,并可以将数据从一个存储系统移动到另一个存储系统。但是,它们以连续流模式运行,而不是定期触发。因此,它们能够从连续产生数据的源读取记录,并以低延迟将其移动到目的地。例如,数据管道可能会监视文件系统目录中的新文件并将其数据写入事件日志。另一个应用程序可能会将事件流具体化到数据库或逐步构建和优化搜索索引。
下图描述了周期性 ETL 作业和连续数据管道之间的区别。
数据管道有哪些优点?
与定期 ETL 作业相比,连续数据管道的明显优势在于减少了将数据移动到目的地的延迟。此外,数据管道更加灵活,可以用于更多用例,因为它们能够连续消费和发送数据。
Flink 如何支持数据管道?
Flink 的 SQL 接口(或 Table API)及其对用户定义函数的支持可以解决许多常见的数据转换或丰富任务。具有更高级要求的数据管道可以通过使用更通用的 DataStream API 来实现。Flink 为各种存储系统(如 Kafka、Kinesis、Elasticsearch 和 JDBC 数据库系统)提供了一组丰富的连接器。它还具有用于监视目录的文件系统的连续源和以时间段方式写入文件的接收器。
Flink 运行时由两种类型的进程组成:一个JobManager和一个或多个TaskManagers。
JobManager
JobManager具有许多与协调 Flink 应用程序的分布式执行相关的职责:它决定何时安排下一个任务(或一组任务)、对已完成的任务或执行失败做出反应、协调检查点以及协调故障恢复等。此过程由三个不同的组件组成:
ResourceManager 资源管理器
ResourceManager负责 Flink 集群中的资源解除/分配和配置 - 它管理任务槽,任务槽是 Flink 集群中的资源调度单位(请参阅TaskManagers)。Flink 为不同的环境和资源提供者(如 YARN、Kubernetes 和独立部署)实现了多个 ResourceManager。在独立设置中,ResourceManager 只能分配可用 TaskManager 的槽,而不能自行启动新的 TaskManager。
Dispatcher 调度员
Dispatcher提供 REST 接口来提交 Flink 应用程序以供执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 来提供有关作业执行的信息。
JobMaster 工作大师
JobMaster负责管理单个 JobGraph的执行。Flink 集群中可以同时运行多个作业,每个作业都有自己的 JobMaster 。
始终至少有一个 JobManager。高可用性设置可能有多个 JobManager,其中一个始终是领导者,其他的是待机的。
TaskManagers
TaskManagers (也称为worker ) 执行数据流的任务,并缓冲和交换数据流。
必须始终至少有一个 TaskManager。TaskManager 中资源调度的最小单位是任务槽。TaskManager 中的任务槽数量表示并发处理任务的数量。请注意,一个任务槽中可以执行多个算子。
对于分布式执行,Flink将运算符子任务链接在一起形成 任务。每个任务由一个线程执行。将运算符链接在一起形成任务是一种有用的优化:它减少了线程间切换和缓冲的开销,并在降低延迟的同时提高了整体吞吐量。可以配置链接行为
下图中的示例数据流由五个子任务执行,因此有五个并行线程。
每个工作器 (TaskManager) 都是一个JVM 进程,可以在单独的线程中执行一个或多个子任务。为了控制 TaskManager 接受的任务数量,它具有所谓的任务槽(至少一个)。
每个任务槽代表 TaskManager 的固定资源子集。例如,具有三个槽的 TaskManager 将为每个槽分配 1/3 的托管内存。将资源划分为槽意味着子任务不会与其他作业的子任务争夺托管内存,而是拥有一定数量的预留托管内存。请注意,这里没有 CPU 隔离;目前槽仅将任务的托管内存分开。
通过调整任务槽的数量,用户可以定义子任务如何相互隔离。每个 TaskManager 有一个槽意味着每个任务组在单独的 JVM 中运行(例如,可以在单独的容器中启动)。拥有多个槽意味着更多子任务共享同一个 JVM。同一个 JVM 中的任务共享 TCP 连接(通过多路复用)和心跳消息。它们还可以共享数据集和数据结构,从而减少每个任务的开销。
默认情况下,Flink 允许子任务共享 slot,即使它们是不同任务的子任务,只要它们来自同一个作业即可。结果是一个 slot 可能容纳该作业的整个管道。允许这种slot 共享有两个主要好处:
参考文献:
Apache Flink 官网
Apache Flink 文档
亚马逊云-什么是 Apache Flink?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。