目录
- 架构
- 处理有界与无界数据
- 部署应用到任意地方
- 运行任意规模应用
- 利用内存性能
- 流应用
- 流处理应用的基本组件
- 流
- 状态
- 时间
- 应用场景
- 事件驱动应用
- 事件驱动应用的优势
- Flink如何支持事件驱动应用?
- 典型的事件驱动示例
- 数据分析应用
- 流式分析应用的优势?
- Flink 如何支持数据分析类应用?
- 典型的数据分析应用实例
- 数据管道应用
- 数据管道的优势?
- Flink 如何支持数据管道应用?
- 典型的数据管道应用实例
- 运行Flink作业在UI界面查看
- 启动和停止本地集群
- 提交Flink任务
- 相关文献
架构
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。
接下来,我们来介绍一下 Flink 架构中的重要方面。
处理有界与无界数据
任何类型的数据都可以形成一种事件流。信用卡交易、传感器测量、机器日志、网站或移动应用程序上的用户交互记录,所有这些数据都形成一种流。
数据可以被作为 无界 或者 有界 流来处理。
- 无界流:
- 有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。
- 有界流:
- 有定义流的开始,也有定义流的结束。有界流可以在摄取所有数据后再进行计算。有界流所有数据可以被排序,所以并不需要有序摄取。有界流处理通常被称为批处理
Apache Flink 擅长处理无界和有界数据集 精确的时间控制和状态化使得 Flink 的运行时(runtime)能够运行任何处理无界流的应用。有界流则由一些专为固定大小数据集特殊设计的算法和数据结构进行内部处理,产生了出色的性能。
举个例子通俗理解:
- 无界流:假如要监听mysql的数据变化去做后续业务处理,那么其中mysql的数据变化,是一个没有开始结束的过程,会一直持续的新增、修改、删除操作,因此这种操作的可以被理解为是一种无界流的数据
- 无界流:假如商品有个活动页,规定了时间开始和结束,时间外不会再有数据进来,这样的数据是一种有限的数据,可以进行批量处理,也叫做批处理数据,有界流数据通常用于离线处理,对数据进行聚合、分组、统计等应用。
部署应用到任意地方
Apache Flink 是一个分布式系统,它需要计算资源来执行应用程序。Flink 集成了所有常见的集群资源管理器,例如 Hadoop YARN、 Apache Mesos 和 Kubernetes,但同时也可以作为独立集群运行。
Flink 被设计为能够很好地工作在上述每个资源管理器中,这是通过资源管理器特定(resource-manager-specific)的部署模式实现的。Flink 可以采用与当前资源管理器相适应的方式进行交互。
部署 Flink 应用程序时,Flink 会根据应用程序配置的并行性自动标识所需的资源,并从资源管理器请求这些资源。在发生故障的情况下,Flink 通过请求新资源来替换发生故障的容器。提交或控制应用程序的所有通信都是通过 REST 调用进行的,这可以简化 Flink 与各种环境中的集成。
Flink还提供了管理界面对Flink中提交的任务进行管理,也可以通过Flink提供的REST API嵌入到应用的业务中快速集成。
运行任意规模应用
Flink 旨在任意规模上运行有状态流式应用。因此,应用程序被并行化为可能数千个任务,这些任务分布在集群中并发执行。所以应用程序能够充分利用无尽的 CPU、内存、磁盘和网络 IO。而且 Flink 很容易维护非常大的应用程序状态。其异步和增量的检查点算法对处理延迟产生最小的影响,同时保证精确一次状态的一致性。
Flink 用户报告了其生产环境中一些令人印象深刻的扩展性数字
- 处理每天处理数万亿的事件,
- 应用维护几TB大小的状态,
- 应用在数千个内核上运行。
利用内存性能
有状态的 Flink 程序针对本地状态访问进行了优化。任务的状态始终保留在内存中,如果状态大小超过可用内存,则会保存在能高效访问的磁盘数据结构中。任务通过访问本地(通常在内存中)状态来进行所有的计算,从而产生非常低的处理延迟。Flink 通过定期和异步地对本地状态进行持久化存储来保证故障场景下精确一次的状态一致性。
注意:Flink的初始化以及运行时,一定要根据当前服务器内存进行参数配置,避免占用大量内存,导致服务器宕机情况发生。
流应用
Flink 自底向上在不同的抽象级别提供了多种 API,并且针对常见的使用场景开发了专用的扩展库。在这里,将介绍 Flink 所提供的这些简单易用、易于表达的 API 和库,可以进行一个简单的基础入门。
流处理应用的基本组件
可以由流处理框架构建和执行的应用程序类型是由框架对 流、状态、时间 的支持程度来决定的
流
(数据)流是流处理的基本要素。然而,流也拥有着多种特征。这些特征决定了流如何以及何时被处理。Flink 是一个能够处理任何类型数据流的强大处理框架。
- 有界 和 无界 的数据流:流可以是无界的;也可以是有界的,例如固定大小的数据集。Flink 在无界的数据流处理上拥有诸多功能强大的特性,同时也针对有界的数据流开发了专用的高效算子。
- 实时 和 历史记录 的数据流:所有的数据都是以流的方式产生,但用户通常会使用两种截然不同的方法处理数据。或是在数据生成时进行实时的处理;亦或是先将数据流持久化到存储系统中——例如文件系统或对象存储,然后再进行批处理。Flink 的应用能够同时支持处理实时以及历史记录数据流。
状态
只有在每一个单独的事件上进行转换操作的应用才不需要状态,换言之,每一个具有一定复杂度的流处理应用都是有状态的。任何运行基本业务逻辑的流处理应用都需要在一定时间内存储所接收的事件或中间结果,以供后续的某个时间点(例如收到下一个事件或者经过一段特定时间)进行访问并进行后续处理。
Flink 提供了许多状态管理相关的特性支持,其中包括:
- 多种状态基础类型:Flink 为多种不同的数据结构提供了相对应的状态基础类型,例如原子值(value),列表(list)以及映射(map)。开发者可以基于处理函数对状态的访问方式,选择最高效、最适合的状态基础类型。
- 插件化的State Backend:State Backend 负责管理应用程序状态,并在需要的时候进行 checkpoint。Flink 支持多种 state backend,可以将状态存在内存或者 RocksDB。RocksDB 是一种高效的嵌入式、持久化键值存储引擎。Flink 也支持插件式的自定义 state backend 进行状态存储。
- 精确一次语义:Flink 的 checkpoint 和故障恢复算法保证了故障发生后应用状态的一致性。因此,Flink 能够在应用程序发生故障时,对应用程序透明,不造成正确性的影响。
- 超大数据量状态:Flink 能够利用其异步以及增量式的 checkpoint 算法,存储数 TB 级别的应用状态。
- 可弹性伸缩的应用:Flink 能够通过在更多或更少的工作节点上对状态进行重新分布,支持有状态应用的分布式的横向伸缩。
也可以简单理解为,类似Java8中的Stream流,在进行collect之后可以对数据再次filter、group等操作,那么在collect中可能会存在数据的衍生数据B,在流数据处理中,衍生数据B是无法直接传递到下一个流,这时候就需要状态,状态相当于这个流的一个本地储存,存在状态里的衍生数据B,就可以在本次流的上下文中都可以进行数据互通。
时间
时间是流处理应用另一个重要的组成部分。因为事件总是在特定时间点发生,所以大多数的事件流都拥有事件本身所固有的时间语义。进一步而言,许多常见的流计算都基于时间语义,例如窗口聚合、会话计算、模式检测和基于时间的 join。流处理的一个重要方面是应用程序如何衡量时间,即区分事件时间(event-time)和处理时间(processing-time)。
Flink 提供了丰富的时间语义支持。
- 事件时间模式:使用事件时间语义的流处理应用根据事件本身自带的时间戳进行结果的计算。因此,无论处理的是历史记录的事件还是实时的事件,事件时间模式的处理总能保证结果的准确性和一致性。
- Watermark 支持:Flink 引入了 watermark 的概念,用以衡量事件时间进展。Watermark 也是一种平衡处理延时和完整性的灵活机制。
- 迟到数据处理:当以带有 watermark 的事件时间模式处理数据流时,在计算完成之后仍会有相关数据到达。这样的事件被称为迟到事件。Flink 提供了多种处理迟到数据的选项,例如将这些数据重定向到旁路输出(side output)或者更新之前完成计算的结果。
- 处理时间模式:除了事件时间模式,Flink 还支持处理时间语义。处理时间模式根据处理引擎的机器时钟触发计算,一般适用于有着严格的低延迟需求,并且能够容忍近似结果的流处理应用。
应用场景
通过上面的了解我们可以知道,它的主要特性包括:批流一体化、精密的状态管理、事件时间支持以及精确一次的状态一致性保障等。接下来我们来看看使用Flink的几种经典的应用场景。
事件驱动应用
事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。
事件驱动型应用是在计算存储分离的传统应用基础上进化而来。在传统架构中,应用需要读写远程事务型数据库。
相反,事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。系统容错性的实现依赖于定期向远程持久化存储写入 checkpoint。下图描述了传统应用和事件驱动型应用架构的区别。
事件驱动应用的优势
事件驱动型应用无须查询远程数据库,本地数据访问使得它具有更高的吞吐和更低的延迟。而由于定期向远程持久化存储的 checkpoint 工作可以异步、增量式完成,因此对于正常事件处理的影响甚微。事件驱动型应用,由于只需考虑自身数据,因此在更改数据表示或服务扩容时所需的协调工作将大大减少。
Flink如何支持事件驱动应用?
Flink 还支持事件时间和自由度极高的定制化窗口逻辑,而且它内置的 <font style="color:rgb(35, 47, 62);">ProcessFunction</font>
支持细粒度时间控制,方便实现一些高级业务逻辑。同时,Flink 还拥有一个复杂事件处理(CEP)类库,可以用来检测数据流中的模式。
Flink 中针对事件驱动应用的明星特性当属 savepoint。Savepoint 是一个一致性的状态映像,它可以用来初始化任意状态兼容的应用。在完成一次 savepoint 后,即可放心对应用升级或扩容,还可以启动多个版本的应用来完成 A/B 测试。
注意:ProcessFunction、Savepoint很重要
典型的事件驱动示例
- 反欺诈
- 异常检测
- 基于规则的报警
- 业务流程监控
- (社交网络)Web 应用
数据分析应用
数据分析任务需要从原始数据中提取有价值的信息和指标。传统的分析方式通常是利用批查询,或将事件记录下来并基于此有限数据集构建应用来完成。为了得到最新数据的分析结果,必须先将它们加入分析数据集并重新执行查询或运行应用,随后将结果写入存储系统或生成报告。
借助一些先进的流处理引擎,还可以实时地进行数据分析。和传统模式下读取有限数据集不同,流式查询或应用会接入实时事件流,并随着事件消费持续产生和更新结果。这些结果数据可能会写入外部数据库系统或以内部状态的形式维护。仪表展示应用可以相应地从外部数据库读取数据或直接查询应用的内部状态。
流式分析应用的优势?
和批量分析相比,由于流式分析省掉了周期性的数据导入和查询过程,因此从事件中获取指标的延迟更低。不仅如此,批量查询必须处理那些由定期导入和输入有界性导致的人工数据边界,而流式查询则无须考虑该问题。
另一方面,流式分析会简化应用抽象。批量查询的流水线通常由多个独立部件组成,需要周期性地调度提取数据和执行查询。如此复杂的流水线操作起来并不容易,一旦某个组件出错将会影响流水线的后续步骤。而流式分析应用整体运行在 Flink 之类的高端流处理系统之上,涵盖了从数据接入到连续结果计算的所有步骤,因此可以依赖底层引擎提供的故障恢复机制。
Flink 如何支持数据分析类应用?
Flink 为持续流式分析和批量分析都提供了良好的支持。具体而言,它内置了一个符合 ANSI 标准的 SQL 接口,将批、流查询的语义统一起来。无论是在记录事件的静态数据集上还是实时事件流上,相同 SQL 查询都会得到一致的结果。同时 Flink 还支持丰富的用户自定义函数,允许在 SQL 中执行定制化代码。如果还需进一步定制逻辑,可以利用 Flink DataStream API 和 DataSet API 进行更低层次的控制。
注意:DataStream、DataSet API很重要。
典型的数据分析应用实例
- 电信网络质量监控
- 移动应用中的产品更新及实验评估分析
- 消费者技术中的实时数据即席分析
- 大规模图分析
数据管道应用
什么是数据管道应用?
提取-转换-加载(ETL)是一种在存储系统之间进行数据转换和迁移的常用方法。ETL 作业通常会周期性地触发,将数据从事务型数据库拷贝到分析型数据库或数据仓库。
数据管道和 ETL 作业的用途相似,都可以转换、丰富数据,并将其从某个存储系统移动到另一个。但数据管道是以持续流模式运行,而非周期性触发。因此它支持从一个不断生成数据的源头读取记录,并将它们以低延迟移动到终点。例如:数据管道可以用来监控文件系统目录中的新文件,并将其数据写入事件日志;另一个应用可能会将事件流物化到数据库或增量构建和优化查询索引。
数据管道的优势?
和周期性 ETL 作业相比,持续数据管道可以明显降低将数据移动到目的端的延迟。此外,由于它能够持续消费和发送数据,因此用途更广,支持用例更多。
Flink 如何支持数据管道应用?
很多常见的数据转换和增强操作可以利用 Flink 的 SQL 接口(或 Table API)及用户自定义函数解决。如果数据管道有更高级的需求,可以选择更通用的 DataStream API 来实现。Flink 为多种数据存储系统(如:Kafka、Kinesis、Elasticsearch、JDBC数据库系统等)内置了连接器。同时它还提供了文件系统的连续型数据源及数据汇,可用来监控目录变化和以时间分区的方式写入文件。
注意:Flink的Table API、Flink的内置连接器很重要,后面的体现为Flink CDC。
典型的数据管道应用实例
- 电子商务中的实时查询索引构建
- 电子商务中的持续 ETL
运行Flink作业在UI界面查看
前提条件:本地需提前安装好jdk11
下载Flink:https://flink.apache.org/downloads/
解压在本地后,进入目录可见如下:
- bin/:目录下包含Flink二进制文件以及管理各种作业和任务的多个bash脚本
- conf/:目录下包含配置文件,包括Flink配置文件
- examples/:目录包含可以按原样与Flink一起使用的示例应用程序
启动和停止本地集群
./bin/start-cluster.sh
会看到如下输出:
Flink 现在作为后台进程运行。可以使用以下命令检查其状态:
ps aux | grep flink
也可以直接打开本地网页,查看Flink仪表板localhost:8081
停止集群和所有正在运行的组件,以下脚本:
./bin/stop-cluster.sh
提交Flink任务
Flink 提供了一个 CLI 工具 bin/flink,它可以运行打包为 Java ARchives (JAR) 的程序并控制其执行。提交任务意味着将作业的 JAR 文件和相关依赖项上传到正在运行的 Flink 集群并执行它。
Flink 版本附带示例任务,您可以在 examples/ 文件夹中找到这些任务。
要将示例字数统计任务部署到正在运行的集群,请发出以下命令:
./bin/flink run examples/streaming/WordCount.jar
可以通过查看日志来验证输出:
tail log/flink-*-taskexecutor-*.out
输出示例:
(nymph,1)(in,3)(thy,1)(orisons,1)(be,4)(all,2)(my,1)(sins,1)(remember,1)(d,4)
还可以检查 Flink 的WEB UI以监控集群和正在运行的任务的状态。
对于任务执行,Flink 有两个运算符。第一个是 source 运算符,它从收集源读取数据。第二个运算符是 transformation 运算符,用于聚合单词计数。
还可以查看任务执行的时间线:
也可以使用自己的jar来去运行,后续将会以demo演示的方式带大家走几个场景去熟悉,今天先到这。
相关文献
- https://flink.apache.org/zh/
- https://nightlies.apache.org/flink/flink-docs-release-1.20/docs/learn-flink/overview/
- https://nightlies.apache.org/flink/flink-cdc-docs-stable/docs/get-started/introduction/
- https://nightlies.apache.org/flink/flink-docs-stable/docs/try-flink/local_installation/
- https://nightlies.apache.org/flink/flink-docs-release-1.20/docs/ops/rest_api/#api
就先说到这 \color{#008B8B}{ 就先说到这} 就先说到这
在下 A p o l l o \color{#008B8B}{在下Apollo} 在下Apollo
一个爱分享 J a v a 、生活的小人物, \color{#008B8B}{一个爱分享Java、生活的小人物,} 一个爱分享Java、生活的小人物,
咱们来日方长,有缘江湖再见,告辞! \color{#008B8B}{咱们来日方长,有缘江湖再见,告辞!} 咱们来日方长,有缘江湖再见,告辞!