一、Flink发展

第一代:Storm

低延迟,无法保证准确性以及很难实现高吞吐量。

第二代:Lambda架构

1-1 Lambda 架构示意图

流处理器和批处理器的简单合并,

数据到达 之后,两层处理双管齐下,一方面由流处理器进行实时处理,另一方面写入批处理存储空间, 等待批处理器批量计算。流处理器快速计算出一个近似结果,并将它们写入“流处理表”中。 而批处理器会定期处理存储中的数据,将准确的结果写入批处理表,并从快速表中删除不准确 的结果。最终,应用程序会合并快速表和批处理表中的结果,并展示出来。 优点:兼具了批处理和第一代流处理器的特点,同时保证了低延迟和结果的准确性。缺点:Lambda架构本身很难建立和维护;而且它需要我们对一个应用程序,做出两套语义上等效的逻辑实现,因为批处理和流处理是两套完全独立的系统,他们的API也完全相同。为了实现一个应用,付出了双倍的工作量,这对程序员显然不够友好。

第三代:Flink

解决了乱序数据对结果正确性的影响。这一代系统还做到了精确一次(exactly-once)的执行保障,是第一个具有一致性和准确结果的开源节流处理器。 另外,先前的流处理器仅能在高吞吐和低延迟中二选一,而新一代系统能够同时提供 这两个特性。所以可以说,这一代流处理器仅凭一套系统就完成了 Lambda 架构两套系统的工 作,它的出现使得 Lambda 架构黯然失色。 除了低延迟、容错和结果准确性之外,新一代流处理器还在不断添加新的功能,例如高可 用的设置,以及与资源管理器(如 YARN Kubernetes)的紧密集成等等

二、Flink的核心特性

Flink区别与传统数据处理框架的特性如下。

  • 高吞吐和低延迟。每秒处理数百万个事件,毫秒级延迟
  • 结果的准确性。Flink提供了事件事件(event-time)和处理时间(processin-time)语义。对于乱序事件流,事件时间语义仍然能提供一致且准确的结果。
  • 精确一次(exactly-once)的状态一致性保证。
  • 可以连接到最常用的存储系统,如 Apache Kafka、Apache Cassandra、Elasticsearch、 JDBC Kinesis 和(分布式)文件系统,如 HDFS S3
  • 高可用。本身高可用的设置,加上与 K8s YARN Mesos 的紧密集成,再加上从故 障中快速恢复和动态扩展任务的能力,Flink 能做到以极少的停机时间 7 × 24 全天候运行。
  • 能够更新应用程序代码并将作业(jobs)迁移到不同的 Flink 集群,而不会丢失应用 程序的状态。

三、分层API

除了上述这些特性之外,Flink还是一个非常易于开发的框架,因为它拥有易于使用的分层API,整体API分层如图1-2所示。

1-2 Flink 不同级别API

四、Flink vs Spark

大数据处理引擎,Apache Spark 是一个通用大规模数据分析引擎。

它提出的内存计算概念让大家耳目一新,得以从 Hadoop 繁重的 MapReduce 程序中解脱出来, 可以说是划时代的大数据处理框架。除了计算速度快、可扩展性强, Spark 还为批处理( Spark SQL )、流处理( Spark Streaming )、机器学习( Spark MLlib )、图计算( Spark GraphX )提供 了统一的分布式数据处理平台,整个生态经过多年的蓬勃发展已经非常完善。

数据处理框架

我们已经知道,数据处理的基本方式,可以分为批处理和流处理两种。批处理针对的是有界的数据集,非常适合需要访问海量的全部数据才能完成的计算工作,一般用于离线统计。流处理主要针对的数据流,特点是无界‘实时,对系统传输的每个数据依次执行操作,一般用于实时统计。从根本上说,Spark Flink 采用了完全不同的数据处理方式。可以说,两者的世界观是 截然相反的。 Spark以批处理为根本,并尝试在批处理之上支持流处理计算;在Spark的世界观中万物接批次,离线数据是一个大批次,而实时数据则是由一个个无限的小批次组成。所以对于流处理框架Spark Streaming而言,其实并不是真正意义上的“流”处理,而是“微批次”(micro-batching)处理如下图1-3

1-3 Spark Streaming流处理示意图

而Flink认为,流处理才是最基本的操作,批处理也可以统一为流处理。在Flink的世界观中,万物皆流,实施数据时标准的、没有界限的流,而离线数据则是有界限的流。 1、无界数据流(UNbounded Data Stream) 所谓无界数据流,就是有头没尾,数据的生成和传递会开始但永远不会结束。如下图1-4,我们无法等待所有的数据都到达,因为输入是无界的,永无止境,数据没有“都到达”的时候。所以对于无界数据流,必须连续处理,也就是说必须在获取数据后立即处理。在处理无界流时,为了保证结果的正确性,我们必须能够做到按照顺序处理数据。

1-4 有界流与无界流

2、有界数据流(Bouned Data Stream) 对应的,有界数据流有明确的开始和结束,如上图1-4,所以我们可以通过获取所有数据来处理有界流。处理有界流就不需要严格保证数据的顺序了,因为总可以对有界数据集进行排序。有界流的处理也就是批处理。 正因为这种架构上的不同,Spark和Flink在不同的应用领域上表现会有差别。一般来说,Spark基于微批处理的方式做同步总有一个“攒批”的过程,所以会有额外开销,因此无法在流处理的低延迟上做到极致。在低延迟流处理场景,Flink已经有明显的优势。而在海量数据的批处理领域,Spark能够处理的吞吐量更大,加上其完善的生态和成熟易用的API,目前同样优势比较明显。

数据模型和运行架构

除了三观不合,Spark Flink 在底层实现最主要的差别就在于数据模型不同。 Spark 底层数据模型是弹性分布式数据集(RDD),Spark Streaming 进行微批处理的底层接口 DStream,实际上处理的也是一组组小批数据 RDD 的集合。可以看出,Spark 在设计上本身就是以批量的数据集作为基准的,更加适合批处理的场景。 而 Flink 的基本数据模型是数据流(DataFlow),以及事件(Event)序列。Flink 基本上是 完全按照 Google DataFlow 模型实现的,所以从底层数据模型上看,Flink 是以处理流式数 据作为设计目标的,更加适合流处理的场景。 数据模型不同,对应在运行处理的流程上,自然也会有不同的架构。Spark 做批计算,需要将任务对应的 DAG 划分阶段(Stage),一个完成后经过 shuffle 再进行下一阶段的计算。而Flink是标准的流式执行模式,一个事件在一个节点处理完后可以直接发往下一个节点进行处理。

Spark 还是 Flink

Spark和Flink可以说目前各擅胜场,批处理领域Spark称王,而在流处理方面Flink当仁不让。具体到项目应用中,不仅要看是流处理还是批处理,还需要在延迟、吞吐量、可靠性,以及开发容易度等多个方面进行权衡。

如果在工作中需要从Spark和Flink这两个主流框架中选择一个来进行实时流处理,我们更加推荐使用Flink,主要的原因有:

  • Flink的延迟是毫秒级别,而Spark Streaming的延迟是秒级延迟。
  • Flink提供了严格的精确一次性语义保证。
  • Flink的窗口API更加灵活,语义丰富。
  • Flink提供事件时间语义,可以正确处理延迟数据。
  • Flink提供了更加灵活的对状态编程的API。

基于以上特点,使用Flink可以解放程序员,加快编程效率,把本来需要程序员花费大力气手动完成的工作交给框架完成。

当然,在海量数据的批处理方面,Spark还是具有明显的优势。而且Spark的生态更加成熟,也会使其在应用中更为方面。