欢迎光临散文网 会员登陆 & 注册

第1章 Flink 基础概念

2023-08-19 20:47 作者:品德与社会课代表  | 我要投稿

1.1、Flink基础概念

1.1.1、Flink是什么

Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算,它的核心目标是“数据流上的有状态计算”(Stateful Computations over Data Streams)。


1.1.2、大数据发展史

大数据的飞速发展,出现了很多热门的开源社区,其中著名的有 Hadoop、Storm、Spark 以及 Flink,他们都有着各自专注的应用场景。

Spark 掀开了内存计算的先河,也以内存为赌注,赢得了内存计算的飞速发展。


  • 第1代--Hadoop MapReduce

首先第一代的计算引擎,无疑就是 Hadoop 承载的 MapReduce。它将计算分为两个阶段,分别为 Map 和 Reduce。对于上层应用来说,就不得不想方设法去拆分算法,甚至于不得不在上层应用实现多个 Job 的串联,以完成一个完整的算法,例如迭代计算。

主要关键词:批处理、Mapper、Reducer


  • 第2代--DAG框架(Tez) + MapReduce

由于这样的弊端,催生了支持 DAG 框架的产生。因此,支持 DAG 的框架被划分为第二代计算引擎。如 Tez 以及更上层的 Oozie。这里我们不去细究各种 DAG 实现之间的区别,不过对于当时的 Tez 和 Oozie 来说,大多还是批处理的任务。

主要关键词:批处理、1个 Tez = MR(1) + MR(2) + ... + MR(n)、相比 MR 效率有所提升


  • 第3代--Spark

接下来就是以 Spark 为代表的第三代的计算引擎。第三代计算引擎的特点主要是 Job 内部的 DAG 支持(不跨越  Job),以及强调的实时计算,其实 Spark Streaming 是以微批(micro-batch)方式对流式数据进行处理。

主要关键词:micro-batch、SQL 高层 API 支持、自带 DAG、内存迭代计算、性能较之前大幅提升


  • 第4代--Flink,Structured Streaming

随着第三代计算引擎的出现,促进了上层应用快速发展,例如各种迭代计算的性能以及对流计算和 SQL 等的支持。Flink 的诞生就被归在了第四代。这应该主要表现在 Flink 对流计算的支持,以及更一步的实时性上面。当然 Flink 也可以支持 Batch 的任务,以及 DAG 的运算。流批一体是当前最流行的处理方式,两套逻辑只需要执行一套代码。

Flink 最重要的特性 Checkpoint 是基于 Chandy-Lamport 算法实现了一个分布式的一致性的快照(Distributed Snapshot),从而提供了一致性的语义。而 Spark 的 Structured Streaming 的 Continuous Processing Mode 的容错处理也是是这个算法。所以用 Spark Streaming 和 Flink 对比是不太恰当的,Structured Streaming 才是合适的参照。在笔者看来,Structured Streaming  和 Flink 的原理都差不多,不过基于阿里强大的生态及大力推广,国内市场用 Flink 的比例比较高。

主要关键词:流批一体、SQL 高层 API 支持、自带 DAG、流式计算性能更高、可靠性更高


1.1.3、有界流和无界流

离线批计算和流式计算,本质上就是对有界流和无界流的计算。


无界数据流

  • 有定义流的开始,但没有定义流的结束

  • 它们会无休止的产生数据

  • 无界流的数据必须持续处理,并输出“当时”的计算结果,因此计算结果也不会是一个一次性的最终结果,而是源源不断的无界结果流。

  • 无界流处理通常被称为流式处理

有界数据流

  • 有定义流的开始,也有定义流的结束;

  • 有界流可以在摄取所有数据后再进行计算;

  • 有界流所有数据可以被排序,所以并不需要有序摄取;

  • 有界流处理通常被称为批处理

1.1.4、流处理和批处理



  • 批处理(Batch analytics)

批处理的处理流程是:统一收集数据 --> 对数据进行批量处理 --> 数据存储或生成报表。就是传统意义上使用类似于 Map Reduce、Hive、Spark Batch 等,对作业进行分析、处理、生成离线报表。

  • 流处理(Streaming analytics)

流处理的处理流程是:源源不断的实时数据 --> 持续不断的处理 --> 不断更新的结果。应用较多的场景比如实时大屏、实时报表等。

传输模型标准

对于一个批处理系统,其节点间数据传输的标准模型是:当一条数据被处理完成后,序列化到缓存中,并不会立刻通过网络传输到下一个节点,当缓存写满,就持久化到本地硬盘上,当所有数据都被处理完成后,才开始将处理后的数据通过网络传输到下一个节点。

对于一个流处理系统,其节点间数据传输的标准模型是:当一条数据被处理完成后,序列化到缓存中,然后立刻通过网络传输到下一个节点,由下一个节点继续处理

这两种数据传输模式是两个极端,对应的是流处理系统对低延迟的要求和批处理系统对高吞吐量的要求。

1.1.5、流批一体

流批一体的执行引擎采用了一种十分灵活的方式,同时支持了这两种数据传输模型,以 Flink 为例,Flink 以缓存块为单位进行网络数据传输,用户可以设置缓存块超时时间和缓存块大小来控制缓冲块传输时机,从而控制 Flink 的延迟性和吞吐量。

  • Flink 以固定的缓存块为单位进行网络数据传输,用户可以通过设置缓存块超时值指定缓存块的传输时机;

  • 如果缓存块的超时值为 0,则 Flink 的数据传输方式类似上文所提到流处理系统的标准模型,此时系统可以获得最低的处理延迟;

  • 如果缓存块的超时值为无限大,则 Flink 的数据传输方式类似上文所提到批处理系统的标准模型,此时系统可以获得最高的吞吐量;

  • 同时缓存块的超时值也可以设置为 0 到无限大之间的任意值。缓存块的超时阈值越小,则 Flink 流处理执行引擎的数据处理延迟越低,但吞吐量也会降低,反之亦然。通过调整缓存块的超时阈值,用户可根据需求灵活地权衡系统延迟和吞吐量;

  • 默认情况下,流中的元素并不会一个一个的在网络中传输,而是缓存起来伺机一起发送(默认为 32KB,通过taskmanager.memory.segment-size设置),这样可以避免导致频繁的网络传输,提高吞吐量,但如果数据源输入不够快的话会导致后续的数据处理延迟,所以可以使用 env.setBufferTimeout(默认100ms),来为缓存填入设置一个最大等待时间。等待时间到了之后,即使缓存还未填满,缓存中的数据也会自动发送;

  • ltimeoutMillis > 0 表示最长等待 timeoutMillis 时间,就会 flush;

  • ltimeoutMillis = 0 表示每条数据都会触发 flush,直接将数据发送到下游,相当于没有 Buffer 了(避免设置为 0,可能导致性能下降);

  • ltimeoutMillis = -1 表示只有等到 buffer满了或 CheckPoint 的时候,才会 flush。相当于取消了 timeout 策略。

1.1.6、有状态流处理

状态是计算过程之中需要存储的数据,可能是数据本身也可能是计算结果。状态在内存中速度快但可靠性差,在分布式系统中则相反。

有状态的流处理就是把流处理需要的额外数据保存成一个“状态”,然后针对这条数据进行处理,并且更新状态。

1.2、Flink的运行模式

1.2.1、Local模式

Flink中的Local-cluster(本地集群)模式,单节点运行,主要用于测试, 学习。

1.2.2、Standalone模式

独立集群模式是独立运行的,由Flink自身提供计算资源,不依赖任何外部的资源管理平台。当然独立也是有代价的,如果资源不足,或者出现故障,没有自动扩展或重分配资源的保证,必须手动处理。所以独立 模式一般只用在开发测试或作业非常少的场景下。

1.2.3、Yarn模式

YARN 上部署的过程是客户端把 Flink 应用提交给 Yarn 的 ResourceManager,Yarn 的 ResourceManager 会 向 Yarn 的 NodeManager 申 请 容 器 。 在 这 些 容 器 上 , Flink 会 部 署 JobManager 和 TaskManager 的实例,从而启动集群。Flink 会根据运行在 JobManger 上的作业 所需要的 Slot 数量动态分配 TaskManager 资源。

在yarn模式下,启动flink集群之前要启动yarn和hadoop,以Yarn模式部署Flink任务时,要求Flink有Hadoop支持的版本。Flink1.10要求Hadoop环境需要保证版本在2.2以上,并且集群中安装有HDFS服务。

1.2.4、K8S 运行模式

容器化部署是如今业界流行的一项技术,基于 Docker 镜像运行能够让用户更加方便地对 应用进行管理和运维。容器管理工具中最为流行的就是 Kubernetes(k8s),而 Flink 也在最近 的版本中支持了 k8s 部署模式。基本原理与 YARN 是类似的。

1.3、Flink特性

1.3.1、自带状态管理机制

Flink 应用程序的状态访问都在本地进行,因为这有助于其提高吞吐量和降低延迟。通常情况下 Flink 应用程序都是将状态存储在 JVM 堆上,但如果状态太大,我们也可以选择将其以结构化数据格式存储在高速磁盘中。

通过状态快照实现的容错,通过状态快照和流重放两种方式的组合,Flink 能够提供可容错的,精确一次计算的语义。这些状态快照在执行时会获取并存储分布式 pipeline 中整体的状态,它会将数据源中消费数据的偏移量记录下来,并将整个 job graph 中算子获取到该数据(记录的偏移量对应的数据)时的状态记录并存储下来。当发生故障时,Flink 作业会恢复上次存储的状态,重置数据源从状态中记录的上次消费的偏移量开始重新进行消费处理。而且状态快照在执行时会异步获取状态并存储,并不会阻塞正在进行的数据处理逻辑。




Flink 为什么要参与状态管理?

在 Flink 不参与管理状态的情况下,我们的应用也可以使用状态,但 Flink 为其管理状态提供了一些引人注目的特性:

  • 本地性: Flink 状态是存储在使用它的机器本地的,并且可以以内存访问速度来获取

  • 持久性: Flink 状态是容错的,例如,它可以自动按一定的时间间隔产生 checkpoint,并且在任务失败后进行恢复

  • 纵向可扩展性: Flink 状态可以存储在集成的 RocksDB 实例中,这种方式下可以通过增加本地磁盘来扩展空间

  • 横向可扩展性: Flink 状态可以随着集群的扩缩容重新分布

  • 可查询性: Flink 状态可以通过使用 状态查询 API 从外部进行查询。

1.3.2、强大的准确性保证

  • exactly-once 状态一致性

  • 事件时间处理

在流式计算领域中,窗口计算的地位举足轻重,但目前大多数框架窗口计算采用的都是系统时间(Process Time),也就是事件传输到计算框架处理时,系统主机的当前时间。Flink 能够支持基于事件时间(Event Time)语义进行窗口计算,这种基于事件驱动的机制使得事件即使乱序到达甚至延迟到达,流系统也能够计算出精确的结果,保持了事件原本产生时的时序性,尽可能避免网络传输或硬件系统的影响

  • 专业的迟到数据处理

1.3.3、灵活丰富的多层API

  • 越顶层越抽象,表达含义越简明,使用越方便

  • 越底层越具体,表达能力越丰富,使用越灵活


Stateful Stream Processing(有状态流处理)

通过底层API(处理函数),对最原始数据加工处理。底层API与DataStream API相集成,可以处理复杂的计算。

DataStream/DataSet API(流处理/批处理)

封装了底层处理函数,提供了通用的模块,比如转换(transformations,包括 map、flatmap等),连接(joins),聚合(aggregations),窗口(windows)操作等。

Flink1.12以后,DataStream API已经实现 真正的流批一体,所以DataSet API已经过时。

Table API

是以表为中心的声明式编程,其中表可能会动态变化。Table API遵循关系模型:表有二维数据结构,类似于关系数据库 中的表;同时API提供可比较的操作,例如select、project、join、group-by、aggregate等。我们可以在表与 DataStream/DataSet 之间无缝 切换,以允许程序将 Table API 与 DataStream 以及 DataSet 混合使用。

SQL

这一层在语法与表达能力上与 Table API 类似,但是是以SQL查询表达式的形式表现程序。SQL抽象与Table API交互密切,同 时SQL查询可以直接在Table API定义的表上执行。  

1.3.4、规模弹性扩展

  • 可扩展的分布式架构

集群级别的资源规模灵活配置,算子粒度的独立并行度灵活配置

  • 支持超大状态管理

  • 增量 checkpoint 机制

1.3.5、强大的运维能力

  • 弹性实施部署机制

  • 高可用配置

本身高可用的设置,加上与K8s,YARN 和 Mesos 的紧密集成,再加上从故障中 快速恢复和动态扩展任务的能力,Flink 能做到以极少的停机时间 7×24 全天候运

  • 保存点恢复机制

Flink 通过 SavePoints 技术将任务执行的快照保存在存储介质上,当任务重启的时候,可以从事先保存的 SavePoints 恢复原有的计算状态。Flink 保存点提供了一个状态化的版本机制,使得能以无丢失状态和最短停机时间的方式更新应用或者回退历史数据。


1.3.6、优秀的性能

  • 低延迟 、高吞吐

在处理大量数据的基础上同时能快速返回计算的结果每秒处理数百万个事件,毫秒级延迟

  • 内存计算

Flink 实现了基于 JVM 的自身管理内存的机制,通过使用散列、索引、缓存和排序有效地进行内存管理,通过序列化/反序列化机制将所有的数据对象转换成二进制在内存中存储,降低数据存储大小的同时,更加有效的利用空间。使其独立于 Java 的默认垃圾收集器,尽可能减少 JVM GC 对系统的影响

1.4、应用场景

1.4.1、数据分析(Data Analytics Applications)

数据分析任务需要从原始数据中提取有价值的信息和指标,Data Analytics Applications 包含 Batch analytics(批处理分析)和Streaming analytics(流处理分析):


Batch analytics 可以理解为周期性查询,Batch Analytics 就是传统意义上使用类似于Map Reduce、Hive、Spark Batch 等,对作业进行分析、处理、生成离线报表。比如Flink应用凌晨从Recorded Events中读取昨天的数据,然后做周期查询运算,最后将数据写入Database 或者 HDFS,或者直接将数据生成报表供公司上层领导决策使用。 Streaming analytics 可以理解为连续性查询:比如实时展示双十一天猫销售 GMV(Gross Merchandise Volume成交总额),用户下单数据需要实时写入消息队列,Flink 应用源源不断读取数据做实时计算,然后不断的将数据更新至 Database 或者 K-VStore,最后做大屏实时展示。

典型实例

  • 电信网络质量监控

  • 移动应用中的产品更新及实验评估分析

  • 消费者技术中的实时数据即席分析

  • 大规模图分析

1.4.2、数据管道(Data Pipeline Applications)

什么是数据管道?提取-转换-加载(ETL)是一种在存储系统之间进行数据转换和迁移的常用方法。ETL 作业通常会周期性地触发,将数据从事务型数据库拷贝到分析型数据库或数据仓库。数据管道和 ETL 作业的用途相似,都可以转换、丰富数据,并将其从某个存储系统移动到另一个。但数据管道是以持续流模式运行,而非周期性触发。因此数据管道支持从一个不断生成数据的源头读取记录,并将它们以低延迟移动到终点。

   例如:数据管道可以用来监控文件系统目录中的新文件,并将其数据写入事件日志;另一个应用可能会将事件流物化到数据库或增量构建和优化查询索引。和周期性 ETL 作业相比,持续数据管道可以明显降低将数据移动到目的端的延迟。此外,由于它能够持续消费和发送数据,因此用途更广,支持用例更多。

下图描述了周期性 ETL 作业和持续数据管道的差异:


Periodic ETL:比如每天凌晨周期性的启动一个Flink ETL Job,读取传统数据库中的数据,然后做ETL,最后写入数据库和文件系统。

   Data Pipeline:比如启动一个Flink 实时应用,数据源(比如数据库、Kafka)中的数据不断的通过Flink Data Pipeline流入或者追加到数据仓库(数据库或者文件系统),或者Kafka消息队列。

Data Pipeline 的核心场景类似于数据搬运并在搬运的过程中进行部分数据清洗或者处理,而整个业务架构是 Periodic ETL,它提供了流式 ETL 或者实时 ETL,能够订阅消息队列的消息并进行处理,清洗完成后实时写入到下游的 Database 或 File system 中。

典型实例

  • 电子商务中的持续 ETL(实时数仓):

当下游要构建实时数仓时,上游则可能需要实时的 Stream ETL。这个过程会进行实时清洗或扩展数据,清洗完成后写入到下游的实时数仓的整个链路中,可保证数据查询的时效性,形成实时数据采集、实时数据处理以及下游的实时查询。

  • 电子商务中的实时查询索引构建(搜索引擎推荐):

搜索引擎这块以淘宝为例,当卖家上线新商品时,后台会实时产生消息流,该消息流经过 Flink 系统时会进行数据的处理、扩展。然后将处理及扩展后的数据生成实时索引,写入到搜索引擎中。这样当淘宝卖家上线新商品时,能在秒级或者分钟级实现搜索引擎的搜索。

1.4.3、事件驱动(Event-driven Applications)

       事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。事件驱动型应用是在计算存储分离的传统应用基础上进化而来。在传统架构中,应用需要读写远程事务型数据库。相反,事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。系统容错性的实现依赖于定期向远程持久化存储写入 checkpoint。下图描述了传统应用和事件驱动型应用架构的区别:

从某种程度上来说,所有的实时的数据处理或者是流式数据处理都应该是属于 Data Driven,流计算本质上是 Data Driven 计算。应用较多的如风控系统,当风控系统需要处理各种各样复杂的规则时,Data Driven 就会把处理的规则和逻辑写入到Datastream 的API 或者是 ProcessFunction 的API 中,然后将逻辑抽象到整个 Flink 引擎,当外面的数据流或者是事件进入就会触发相应的规则,这就是 Data Driven 的原理。在触发某些规则后,Data Driven 会进行处理或者是进行预警,这些预警会发到下游产生业务通知,这是 Data Driven 的应用场景,Data Driven 在应用上更多应用于复杂事件的处理。预警的流程如下图:

典型实例

  • 欺诈检测(Fraud detection)

  • 异常检测(Anomaly detection)

  • 基于规则的告警(Rule-based alerting)

  • 业务流程监控(Business process monitoring)

  • Web应用程序(社交网络)


第1章 Flink 基础概念的评论 (共 条)

分享到微博请遵守国家法律