Flink vs Spark
Apache Spark和Flink都是下一代大数据工具抢占业界关注的焦点。两者都提供与Hadoop和NoSQL数据库的本机连接,并且可以处理HDFS数据。两者都是几个大数据的好方法问题。但由于其底层架构,Flink比Spark更快。Apache Spark是Apache存储库中最活跃的组件。Spark拥有非常强大的社区支持,并且拥有大量的贡献者。Spark已经在生产中部署。但就流媒体功能而言,Flink远比Spark好(因为spark以微批量形式处理流)并且具有对流的本机支持。Spark被认为是大数据的3G,而Flink则被视为大数据的4G。
Spark简介
Spark的历史比较悠久,已经发展了很长时间,目前在大数据领域也有了一定的地位.Spark是Apache的一个*项目。它是一种快速的、轻量级、基于内存、分布式迭代计算的大数据处理框架。,Spark最初由美国加州伯克利大学(UCBerkeley)的AMP(Algorithms,Machines and People)实验室与2009年开发,是基于内存计算的大数据并行计算框架,可用于构建大型的、低延迟的数据分析应用程序。2003年加入Apache孵化器项目后的到迅猛的发展,如今已成为Apache的*项目。
Flink简介
Flink出来的时间比较晚,可以说是大数据流计算的新贵,但是发展速度很快,劲头不容小觑,到2016年的时候才崭露头角,Stratosphere 项目最早在 2010 年 12 月由德国柏林理工大学教授 Volker Markl 发起,主要开发人员包括 Stephan Ewen、F* Hueske。Stratosphere 是以 MapReduce 为超越目标的系统,同时期有加州大学伯克利 AMP 实验室的 Spark。相对于 Spark,Stratosphere 是个彻底失败的项目。其实刚开始的时候Flink也是做批处理的,但是当时,spark已经在批处理领域有所建树,所以Flink决定放弃批处理,直接在流处理方面发力.所以 Volker Markl 教授参考了谷歌的流计算最新论文 MillWheel,决定以流计算为基础,开发一个流批结合的分布式流计算引擎 Flink。Flink 于 2014 年 3 月进入 Apache 孵化器并于 2014 年 11 月毕业成为 Apache *项目。
计算模型的区别
两者最重要的区别就是计算模型的不同(微批和流):
1、Micro Batching 模式(spark)
Micro-Batching 计算模式:流计算就是将连续不断的批进行持续计算,如果批足够小那么就有足够小的延时,在一定程度上满足了99%的实时计算场景。那么那1%为啥做不到呢?这就是架构的魅力,在Micro-Batching模式的架构实现上就有一个自然流数据流入系统进行攒批的过程,这在一定程度上就增加了延时。
Micro-Batching 模式的思想就是把输入的数据,分成微小的批次,然后一个批次一个批次的处理,然后也是一个批次一个批次的输出。很显然Micro-Batching模式有其天生的低延时瓶颈,但任何事物的存在都有两面性,在大数据计算的发展历史上,最初Hadoop上的MapReduce就是优秀的批模式计算框架,Micro-Batching在设计和实现上可以借鉴很多成熟实践。
2、Native Streaming 模式(flink)
Native Streaming 计算模式认为 ""批是流的特例",这个认知更贴切流的概念,比如一些监控类的消息流,数据库操作的binlog,实时的支付交易信息等等自然流数据都是一条,一条的流入。Native Streaming 计算模式每条数据的到来都进行计算,这种计算模式显得更自然,并且延时性能达到更低。
Native Streaming 模型可以将输入的数据过来一条处理一条,然后输出,几乎不存在延迟,很明显Native Streaming模式占据了流计算领域 "低延时" 的核心竞争力。当然Native Streaming模式的框架实现上面很容易实现Micro-Batching和Batching模式的计算,另外,目前大数据领域主流的是流批统一,而Apache Flink就是Native Streaming计算模式的流批统一的计算引擎。
数据模型区别
1、基础概念
无边界数据,其实就是一种可增长,无限的数据集。我们无法判断他到底会在什么时候结束。例如:我们生活中的支付宝中的交易数据,每时每刻都会有数据产生,无法判断它什么时候会停止发送。我们也可以称他为”流数据(Streaming Data)“。
有边界数据,其实就是一种保存好了的数据,例如数据库中的数据或者csv中的数据等。拿我们之前的交易数据来说,如果按照一定的时间窗口,拿取一小部分数据,那么提取出来的数据也是有边界数据了。例如我提取2019年08月19日这天地数据来做处理,我们提取出来地这份数据就是有边界数据。
批处理:数据的批处理,可以理解为一系列相关的任务按顺序或并行的,一个接一个地执行。批处理地输入是在一段时间内收集好地数据。每次批处理地输出都可以是下次批处理地输入。
大部分情况下,批处理地输入数据和输出数据都是有边界数据。所以在批处理中,我们更关注地事件事件。批处理的系统架构通常会被设计在:日志分析、账单处理、数据仓库等;
流处理:数据的流处理可以理解为系统需要接收并处理一系列连续不断变化的数据。例如,音视频的实时推荐、周边推荐等。流处理的输入基本都是无边界数据。而流处理系统中是关心事件时间还是处理时间一般是随应用场景而定的。流处理的特点应该是足够快、低延迟、以及来自各种数据源的大规模数据。流处理所需的响应时间更应该以毫秒(或秒)来进行计算。向我们平时用到的搜索引擎,系统必须在用户输入关键字后以毫秒级的延时返回搜索结果给用户。流处理快的原因,是因为他是在数据未达到磁盘时计算的,也就是在内存中计算的。流处理的应用场景有:实时监控、实时交易等。
2、Spark的数据模型
Spark 最早采用 RDD 模型,达到比 MapReduce 计算快 100 倍的显著优势,对 Hadoop 生态大幅升级换代。RDD 弹性数据集是分割为固定大小的批数据,RDD 提供了丰富的底层 API 对数据集做操作。为持续降低使用门槛,Spark 社区开始开发高阶 API:DataFrame/DataSet,Spark SQL 作为统一的 API,掩盖了底层,同时针对性地做 SQL 逻辑优化和物理优化,非堆存储优化也大幅提升了性能。
Spark Streaming 里的 DStream 和 RDD 模型类似,把一个实时进来的无限数据分割为一个个小批数据集合 DStream,定时器定时通知处理系统去处理这些微批数据。劣势非常明显,API 少、难胜任复杂的流计算业务,调大吞吐量而不触发背压是个体力活。不支持乱序处理,或者说很难处理乱序的问题。Spark Streaming 仅适合简单的流处理,这里稍微解释一下,因为spark的创始人在当时认为延迟不是那么的重要,他认为现实生活中没有那么多低延迟的应用场景,所以就没太注重延迟的问题,但是随着生活多样化场景的不断增加,对实时性的要求越来越高,所以spark也注意到了这个问题,开始在延迟方面发力,进而推出了Structured Streaming,相信很快sparkstreaming就会被Structured Streaming替代掉。
Spark Structured Streaming 提供了微批和流式两个处理引擎。微批的 API 虽不如 Flink 丰富,窗口、消息时间、trigger、watermarker、流表 join、流流 join 这些常用的能力都具备了。时延仍然保持最小 100 毫秒。当前处在试验阶段的流式引擎,提供了 1 毫秒的时延,但不能保证 exactly-once 语义,支持 at-least-once 语义。同时,微批作业打了快照,作业改为流式模式重启作业是不兼容的。这一点不如 Flink 做的完美。当然了现在还在优化阶段。
综上,Spark Streaming 和 Structured Streaming 是用批计算的思路做流计算。其实,用流计算的思路开发批计算才是最合理的。对 Spark 来讲,大换血不大可能,只有局部优化。其实,Spark 里 core、streaming、structured streaming、graphx 四个模块,是四种实现思路,通过上层 SQL 统一显得不纯粹和谐。
3、Flink的数据模型
Flink 的基本数据模型是数据流,及事件(Event)的序列。数据流作为数据的基本模型可能没有表或者数据块直观熟悉,但是可以证明是完全等效的。流可以是无边界的无限流,即一般意义上的流处理。也可以是有边界的有限流,这样就是批处理。
Flink 采用 Dataflow 模型,和 Lambda 模式不同。Dataflow 是纯粹的节点组成的一个图,图中的节点可以执行批计算,也可以是流计算,也可以是机器学习算法,流数据在节点之间流动,被节点上的处理函数实时 apply 处理,节点之间是用 netty 连接起来,两个 netty 之间 keepalive,网络 buffer 是自然反压的关键。经过逻辑优化和物理优化,Dataflow 的逻辑关系和运行时的物理拓扑相差不大。这是纯粹的流式设计,时延和吞吐理论上是最优的。
运行时架构
1、Spark运行时架构
批计算是把 DAG 划分为不同 stage,DAG 节点之间有血缘关系,在运行期间一个 stage 的 task 任务列表执行完毕,销毁再去执行下一个 stage;
Spark Streaming 则是对持续流入的数据划分一个批次,定时去执行批次的数据运算;
Structured Streaming 将无限输入流保存在状态存储中,对流数据做微批或实时的计算,跟 Dataflow 模型比较像。
2、Flink运行时架构
Flink 有统一的 runtime,在此之上可以是 Batch API、Stream API、ML、Graph、CEP 等,DAG 中的节点上执行上述模块的功能函数,DAG 会一步步转化成 ExecutionGraph,即物理可执行的图,最终交给调度系统。节点中的逻辑在资源池中的 task 上被 apply 执行,task 和 Spark 中的 task 类似,都对应线程池中的一个线程。
在 DAG 的执行上,Spark 和 Flink 有一个比较显著的区别。在 Flink 的流执行模式中,一个事件在一个节点处理完后的输出就可以发到下一个节点立即处理。这样执行引擎并不会引入额外的延迟。与之相应的,所有节点是需要同时运行的。而 Spark 的 micro batch 和一般的 batch 执行一样,处理完上游的 stage 得到输出之后才开始下游的 stage。在流计算的运行时架构方面,Flink 明显更为统一且优雅一些。
时延和吞吐
至于延迟和吞吐方面,Spark Streaming是秒级别的,Structured Streaming是毫秒级别的;Flink是亚秒级别的,其实这个没差多少。吞吐量的话,测试的结果是Flink是Spark的1.X倍.也相差不是太大。
反压
Flink 中,下游的算子消费流入到网络 buffer 的数据,如果下游算子处理能力不够,则阻塞网络 buffer,这样也就写不进数据,那么上游算子发现无法写入,则逐级把压力向上传递,直到数据源,这种自然反压的方式非常合理。Spark Streaming 是设置反压的吞吐量,到达阈值就开始限流,从批计算上来看是合理的。从这点看Flink的反压机制是要比spark好的。
状态存储
Spark 的快照 API 是 RDD 基础能力,定时开启快照后,会对同一时刻整个内存数据持久化。Spark 一般面向大数据集计算,内存数据较大,快照不宜太频繁,会增加集群计算量。spark的状态管理目前做的比较简单,只有两个对应的算子。
Flink 提供文件、内存、RocksDB 三种状态存储,可以对运行中的状态数据异步持久化。打快照的机制是给 source 节点的下一个节点发一条特殊的 savepoint 或 checkpoint 消息,这条消息在每个算子之间流动,通过协调者机制对齐多个并行度的算子中的状态数据,把状态数据异步持久化。
Flink 打快照的方式,是我见过最为优雅的一个。Flink 支持局部恢复快照,作业快照数据保存后,修改作业,DAG 变化,启动作业恢复快照,新作业中未变化的算子的状态仍旧可以恢复。而且 Flink 也支持增量快照,面对内存超大状态数据,增量无疑能降低网络和磁盘开销。我们会发现Flink的状态存储也有较多的选择。
API方面
Spark 的初衷之一就是用统一的编程模型来解决用户的各种需求,在这方面一直很下功夫。最初基于 RDD 的 API 就可以做各种类型的数据处理。后来为了简化用户开发,逐渐推出了更高层的 DataFrame(在 RDD 中加了列变成结构化数据)和 Datasets(在 DataFrame 的列上加了类型),并在 Spark 2.0 中做了整合(DataFrame = DataSet[Row])。Spark SQL 的支持也比较早就引入了。在加上各个处理类型 API 的不断改进,比如 Structured Streaming 以及和机器学习深度学习的交互,到了今天 Spark 的 API 可以说是非常好用的,也是 Spark 最强的方面之一。
Flink 的 API 也有类似的目标和发展路线。Flink 和 Spark 的核心 API 可以说是可以基本对应的。今天 Spark API 总体上更完备一下,比如说最近一两年大力投入的和机器学习深度学习的整合方面。Flink 在流处理相关的方面还是领先一些,比如对 watermark、window、trigger 的各种支持要比spark好很多。