Apache Flink 是业界公认的最佳流计算引擎之一,它不仅仅局限于流处理,而是一套兼具流、批、机器学习等多种计算功能的大数据引擎。Flink 的用户只需根据业务逻辑开发一套代码,就能够处理全量数据、增量数据和实时数据,无需针对不同的数据类型开发不同的方案。这使得 Flink 成为大数据处理领域中的一款强大工具,可以帮助您构建高效、可靠的大数据处理系统。
希望通过本专题,让大家更全面地了解 Apache Flink 背后的技术,更加得心应手地使用Apache Flink。
Apache Flink 是一款高效的分布式大数据处理引擎,它能够对有限数据流和无限数据流进行有状态或无状态的计算,具有出色的扩展性和容错性。Flink 能够轻松地部署在各种集群环境中,并且能够快速地处理各种规模大小的数据。
在学习 Flink 应用开发之前,您需要先了解 Flink 的 Streams、State、Time 等基础处理语义,以及 Flink 的多层次 API。Flink 为开发人员提供了灵活性和方便性,可以根据不同的需求选择不同的 API。无论是数据流处理还是批处理,Flink 都能够满足您的需求。同时,Flink 还提供了状态管理和时间处理等功能,可以帮助您更好地处理数据。
流数据可以分为有限数据流和无限数据流。
无限数据流被称为不受限制的数据流,因为它们没有固定的结束点,数据会随着时间的推移而持续增加,在处理无限数据流时,计算是持续进行的,因为数据不会停止。
有限数据流是有始有终的数据集合,它们有一个固定的大小,并且最终会被处理完毕。在处理有限数据流时,计算最终会完成并处于结束状态。
有限数据流和无限数据流它们需要不同的处理方法和算法。对于大多数数据处理应用程序来说,都需要处理无限数据流,因此需要使用流式处理框架来处理这些数据。
在计算过程中,数据信息对于容错恢复和 Checkpoint 非常重要。流计算本质上是增量处理,因此需要不断查询并保持状态。为了确保 Exactly-once 语义,需要将数据写入状态中。持久化存储可以确保在整个分布式系统运行失败或挂掉的情况下,实现 Exactly-once 语义,这是状态的另一个重要价值。因此,在流计算中,状态管理是非常关键的。通过持久化存储,可以保证数据的一致性和可靠性,从而确保计算结果的准确性。流计算需要具备高可用性和容错性,这样才能保证数据的连续性和正确性。
Flink的无限数据流可以分为三个时间概念:事件时间( Event time)、摄入时间(Ingestion time)和处理时间(Processing time)。这个过程是持续不断的,时间是我们判断业务状态是否滞后以及数据处理是否及时的重要依据。
通常情况下,API可以分为三个层次,从上到下分别是SQL/Table API、DataStream API和ProcessFunction。API具有强大的表达能力和业务抽象能力,但随着接近SQL层,表达能力会逐渐减弱,抽象能力会增强。相反,ProcessFunction层的API表达能力非常强,可以进行多种灵活方便的操作,但相对抽象能力较小。
在架构部分,主要分为以下四点:
Flink是一种具备处理有界和无界两种数据流的能力的统一框架。
Flink的部署非常灵活,底层支持多种资源调度器,包括Yarn、Kubernetes等。同时,Flink自带的Standalone调度器也非常灵活,可以轻松部署。
Flink具有极高的可伸缩性,这对于分布式系统来说非常重要。例如,阿里巴巴双11大屏采用Flink处理海量数据,其峰值可达17亿/秒。
Flink具有极致的流式处理性能。相较于Storm,Flink最大的特点是将状态语义完全抽象到框架中,支持本地状态读取,避免了大量的网络IO,从而可以极大地提升状态存取的性能。
简单介绍说明 Flink 关于运维及业务监控的内容,具体内容还是会在后面的内容进行介绍和分析说明。
Flink具备7x24小时高可用的SOA(面向服务架构),原因是在实现上Flink提供了一致性的Checkpoint。Checkpoint是Flink实现容错机制的核心,它周期性地记录计算过程中Operator的状态,并生成快照持久化存储。当Flink作业发生故障崩溃时,可以有选择地从Checkpoint中恢复,保证了计算的一致性。
Flink本身提供监控、运维等功能或接口,并有内置的WebUI,对运行的作业提供DAG图以及各种Metric等,协助用户管理作业状态。这些功能和接口使得Flink作业的管理变得更加简单和高效。
Data Pipeline的核心场景是类似于数据搬运,同时在搬运的过程中进行部分数据清洗或处理。在整个业务架构图的左侧是Periodic ETL,它提供了流式ETL或实时ETL,能够订阅消息队列的消息并进行处理、清洗,最终实时写入到下游的数据库或文件系统中。以下是场景举例:
当下游需要构建实时数仓时,上游可能需要进行实时的 Stream ETL,以进行实时的数据清洗或扩展。这个过程将确保数据的时效性,并将清洗后的数据写入到下游的实时数仓中,形成实时数据采集、实时数据处理和下游的实时查询的完整链路。
以淘宝为例,当卖家上线新商品时,后台会实时产生消息流。该消息流经过 Flink 系统进行数据处理和扩展,生成实时索引并写入搜索引擎中。这样,当淘宝卖家上线新商品时,搜索引擎能够在秒级或分钟级实现搜索,提高用户体验。
Data Analytics,如图所示,左边是 Batch Analytics,右边是 Streaming Analytics。Batch Analytics通常使用类似于Map Reduce、Hive、Spark Batch等传统技术,对作业进行离线分析、处理和生成报表。而Streaming Analytics则使用流式分析引擎如Storm、Flink等实时处理和分析数据,适用于实时大屏、实时报表等场景。
在某种程度上,所有实时数据处理或流式数据处理都属于数据驱动,而流计算本质上就是数据驱动计算。其中,风控系统是应用最广泛的领域之一。当风控系统需要处理各种复杂规则时,数据驱动会将处理规则和逻辑写入到Datastream的API或ProcessFunction的API中,并将逻辑抽象到整个Flink引擎中。当外部数据流或事件进入时,相应的规则将被触发,这就是数据驱动的原理。一旦某些规则被触发,数据驱动会进行处理或预警,并将这些预警发送到下游以产生业务通知。因此,数据驱动在复杂事件处理方面应用广泛。
传统批处理数据是指一种数据处理方式,它通过将数据分成批次,逐一处理每个批次中的数据,以达到数据处理的目的。传统批处理数据通常使用批处理作业来完成,这些作业由一系列的命令和程序组成,这些命令和程序会按照一定的顺序依次执行,以完成特定的数据处理任务。
传统批处理数据通常适用于处理大量的数据,这些数据需要进行复杂的计算和分析,例如财务数据、人口统计数据等。由于批处理数据可以在非工作时间进行处理,因此可以有效地减少系统负载和运行成本,提高数据处理的效率和精度。
传统批处理方法是持续收取数据,以时间作为划分多个批次的依据,再周期性地执行批次运算。但假设需要计算每小时出现事件转换的次数,如果事件转换跨越了所定义的时间划分,传统批处理会将中介运算结果带到下一个批次进行计算;除此之外,当出现接收到的事件顺序颠倒情况下,传统批处理仍会将中介状态带到下一批次的运算结果中,这种处理方式也不尽如人意。
有状态流处理作为一个新的持续处理的范例连续的数据
产生准确的结果
实时可用的结果只有一个模型的自然结果
首先,该方法需要具备状态累积和维护的能力,以便维护过去历史中接收到的所有事件,从而影响输出结果。这可以通过使用流式处理引擎来实现,这种引擎可以在处理过程中维护状态,而不是将状态保存在批处理中。
其次,该方法需要具备时间控制机制,以确保数据的完整性。当所有数据都完全接收到后,输出计算结果。这可以通过在流式处理引擎中设置时间窗口来实现,时间窗口可以控制在多长时间内接收数据。
最后,该方法需要能够实时产生结果,并采用新的持续性数据处理模型来处理实时数据,以最大程度地符合 continuous data 的特性。这可以通过使用实时流处理引擎来实现,这种引擎可以在处理数据时实时产生结果,而不是等待一段时间再进行批处理。
流式处理通常用于需要实时响应数据的应用程序,例如实时监控、实时分析和实时报警等。流式处理通常具有以下特点:
流式处理简单来说是指有一个持续不断的数据源不断地收集数据,数据经过代码处理后即时产生结果,并输出。这种处理方式的基本原理是使用代码作为数据处理的基础逻辑,将数据源中的数据流式地传输到处理引擎中,处理引擎会对数据进行实时处理,并输出结果。与批处理不同,流式处理不需要等待所有数据都被收集完毕后再进行处理,而是可以在数据源不断产生数据的同时进行处理。这种处理方式可以使数据处理更加实时、高效,并且可以应用于需要持续监测和处理数据的场景,如实时监测交通流量、实时监测天气数据等。
假设有多个使用者使用 Input Streams,每个使用者都有自己的ID。如果我们需要计算每个使用者出现的次数,我们需要将同一使用者的事件流到同一个运算代码中。这个过程类似于批处理中的group by,需要对数据进行分区,并设置相应的键值。然后,将具有相同键值的数据流传输到同一个计算实例中进行相同的运算。这样可以确保每个使用者的数据被正确地处理,并且可以提高处理效率。
在上述代码中,定义了变量X,X会在数据处理过程中进行读写。在输出结果时,根据变量X的值来决定输出的内容。因此,状态X会影响最终的输出结果。在这个过程中,第一个重点是先进行状态的co-partitioned key by。这样,具有相同键值的数据会流到同一个计算实例中,与使用者出现次数的原理相同。这个状态就是使用者出现的次数,会随着具有相同键值的事件在同一个计算实例中进行累积。
根据输入流的键值重新分区后,状态也会变成co-partition状态,即具有相同键值的状态会被累积到同一个流中。第二个重点是嵌入式本地状态后端。在具有状态的分散式流式处理引擎中,状态可能会累积到非常大,特别是当键值非常多时,状态可能会超出单一节点的内存负荷量。因此,必须有状态后端来维护这些状态。在正常情况下,状态后端可以使用内存来维护这些状态。
总之,传统批处理数据是一种基于批处理作业的数据处理方式,它可以有效地处理大量的数据,并且可以在非工作时间进行处理,从而提高数据处理的效率和精度。
流式处理是一种数据处理方式,它能够在数据到达时及时对其进行处理。与批处理不同,流式处理是在数据流中逐个处理数据,而不是将所有数据收集起来一次性处理。