2019独角兽企业重金招聘Python工程师标准>>>
1.Flink架构及特性分析
Flink是个相当早的项目,开始于2008年,但只在最近才得到注意。Flink是原生的流处理系统,提供high level的API。Flink也提供 API来像Spark一样进行批处理,但两者处理的基础是完全不同的。Flink把批处理当作流处理中的一种特殊情况。在Flink中,所有 的数据都看作流,是一种很好的抽象,因为这更接近于现实世界。
1.1 基本架构
下面我们介绍下Flink的基本架构,Flink系统的架构与Spark类似,是一个基于Master-Slave风格的架构。
当 Flink 集群启动后,首先会启动一个 JobManger 和一个或多个的 TaskManager。由 Client 提交任务给 JobManager, JobManager 再调度任务到各个 TaskManager 去执行,然后 TaskManager 将心跳和统计信息汇报给 JobManager。 TaskManager 之间以流的形式进行数据的传输。上述三者均为独立的 JVM 进程。
Client 为提交 Job 的客户端,可以是运行在任何机器上(与 JobManager 环境连通即可)。提交 Job 后,Client 可以结束进程 (Streaming的任务),也可以不结束并等待结果返回。
JobManager 主要负责调度 Job 并协调 Task 做 checkpoint,职责上很像 Storm 的 Nimbus。从 Client 处接收到 Job 和 JAR 包 等资源后,会生成优化后的执行计划,并以 Task 的单元调度到各个 TaskManager 去执行。
TaskManager 在启动的时候就设置好了槽位数(Slot),每个 slot 能启动一个 Task,Task 为线程。从 JobManager 处接收需要 部署的 Task,部署启动后,与自己的上游建立 Netty 连接,接收数据并处理。
JobManager
JobManager是Flink系统的协调者,它负责接收Flink Job,调度组成Job的多个Task的执行。同时,JobManager还负责收集Job 的状态信息,并管理Flink集群中从节点TaskManager。JobManager所负责的各项管理功能,它接收到并处理的事件主要包括:
RegisterTaskManager
在Flink集群启动的时候,TaskManager会向JobManager注册,如果注册成功,则JobManager会向TaskManager回复消息 AcknowledgeRegistration。
SubmitJob
Flink程序内部通过Client向JobManager提交Flink Job,其中在消息SubmitJob中以JobGraph形式描述了Job的基本信息。
CancelJob
请求取消一个Flink Job的执行,CancelJob消息中包含了Job的ID,如果成功则返回消息CancellationSuccess,失败则返回消息 CancellationFailure。
UpdateTaskExecutionState
TaskManager会向JobManager请求更新ExecutionGraph中的ExecutionVertex的状态信息,更新成功则返回true。
RequestNextInputSplit
运行在TaskManager上面的Task,请求获取下一个要处理的输入Split,成功则返回NextInputSplit。
JobStatusChanged
ExecutionGraph向JobManager发送该消息,用来表示Flink Job的状态发生的变化,例如:RUNNING、CANCELING、 FINISHED等。
TaskManager
TaskManager也是一个Actor,它是实际负责执行计算的Worker,在其上执行Flink Job的一组Task。每个TaskManager负责管理 其所在节点上的资源信息,如内存、磁盘、网络,在启动的时候将资源的状态向JobManager汇报。TaskManager端可以分成两个 阶段:
注册阶段
TaskManager会向JobManager注册,发送RegisterTaskManager消息,等待JobManager返回AcknowledgeRegistration,然 后TaskManager就可以进行初始化过程。
可操作阶段
该阶段TaskManager可以接收并处理与Task有关的消息,如SubmitTask、CancelTask、FailTask。如果TaskManager无法连接 到JobManager,这是TaskManager就失去了与JobManager的联系,会自动进入“注册阶段”,只有完成注册才能继续处理Task 相关的消息。
Client
当用户提交一个Flink程序时,会首先创建一个Client,该Client首先会对用户提交的Flink程序进行预处理,并提交到Flink集群中处 理,所以Client需要从用户提交的Flink程序配置中获取JobManager的地址,并建立到JobManager的连接,将Flink Job提交给 JobManager。Client会将用户提交的Flink程序组装一个JobGraph, 并且是以JobGraph的形式提交的。一个JobGraph是一个 Flink Dataflow,它由多个JobVertex组成的DAG。其中,一个JobGraph包含了一个Flink程序的如下信息:JobID、Job名称、配 置信息、一组JobVertex等。
1.2 基于Yarn层面的架构
基于yarn层面的架构类似spark on yarn模式,都是由Client提交App到RM上面去运行,然后RM分配第一个container去运行 AM,然后由AM去负责资源的监督和管理。需要说明的是,Flink的yarn模式更加类似spark on yarn的cluster模式,在cluster模式 中,dirver将作为AM中的一个线程去运行,在Flink on yarn模式也是会将JobManager启动在container里面,去做个driver类似 的task调度和分配,YARN AM与Flink JobManager在同一个Container中,这样AM可以知道Flink JobManager的地址,从而 AM可以申请Container去启动Flink TaskManager。待Flink成功运行在YARN集群上,Flink YARN Client就可以提交Flink Job到 Flink JobManager,并进行后续的映射、调度和计算处理。
1.3 组件栈
Flink是一个分层架构的系统,每一层所包含的组件都提供了特定的抽象,用来服务于上层组件。
Deployment层
该层主要涉及了Flink的部署模式,Flink支持多种部署模式:本地、集群(Standalone/YARN)、云(GCE/EC2)。Standalone 部署模式与Spark类似,这里,我们看一下Flink on YARN的部署模式
Runtime层
Runtime层提供了支持Flink计算的全部核心实现,比如:支持分布式Stream处理、JobGraph到ExecutionGraph的映射、调度等 等,为上层API层提供基础服务。
API层
API层主要实现了面向无界Stream的流处理和面向Batch的批处理API,其中面向流处理对应DataStream API,面向批处理对应DataSet API。
Libraries层
该层也可以称为Flink应用框架层,根据API层的划分,在API层之上构建的满足特定应用的实现计算框架,也分别对应于面向流处理 和面向批处理两类。面向流处理支持:CEP(复杂事件处理)、基于SQL-like的操作(基于Table的关系操作);面向批处理支持: FlinkML(机器学习库)、Gelly(图处理)。
从官网中我们可以看到,对于Flink一个最重要的设计就是Batch和Streaming共同使用同一个处理引擎,批处理应用可以以一种特 殊的流处理应用高效地运行。
这里面会有一个问题,就是Batch和Streaming是如何使用同一个处理引擎进行处理的。
1.4 Batch和Streaming是如何使用同一个处理引擎。
下面将从代码的角度去解释Batch和Streaming是如何使用同一处理引擎的。首先从Flink测试用例来区分两者的区别。
Batch WordCount Examples
Streaming WordCount Examples
Batch和Streaming采用的不同的ExecutionEnviroment,对于ExecutionEnviroment来说读到的源数据是一个DataSet,而 StreamExecutionEnviroment的源数据来说则是一个DataStream。
接着我们追踪下Batch的从Optimzer到JobGgraph的流程,这里如果是Local模式构造的是LocalPlanExecutor,这里我们只介绍 Remote模式,此处的executor为RemotePlanExecutor
最终会调用ClusterClient的run方法将我们的应用提交上去,run方法的第一步就是获取jobGraph,这个是client端的操作,client 会将jobGraph提交给JobManager转化为ExecutionGraph。Batch和streaming不同之处就是在获取JobGraph上面。
如果我们初始化的FlinkPlan是StreamingPlan,则首先构造Streaming的StreamingJobGraphGenerator去将optPlan转为 JobGraph,Batch则直接采用另一种的转化方式。
简而言之,Batch和streaming会有两个不同的ExecutionEnvironment,不同的ExecutionEnvironment会将不同的API翻译成不同 的JobGgrah,JobGraph 之上除了 StreamGraph 还有 OptimizedPlan。OptimizedPlan 是由 Batch API 转换而来的。 StreamGraph 是由 Stream API 转换而来的,JobGraph 的责任就是统一 Batch 和 Stream 的图。
1.5 特性分析
高吞吐 & 低延迟
Flink 的流处理引擎只需要很少配置就能实现高吞吐率和低延迟。下图展示了一个分布式计数的任务的性能,包括了流数据 shuffle 过程。
支持 Event Time 和乱序事件
Flink 支持了流处理和 Event Time 语义的窗口机制。
Event time 使得计算乱序到达的事件或可能延迟到达的事件更加简单。
状态计算的 exactly-once 语义
流程序可以在计算过程中维护自定义状态。
Flink 的 checkpointing 机制保证了即时在故障发生下也能保障状态的 exactly once 语义。
高度灵活的流式窗口
Flink 支持在时间窗口,统计窗口,session 窗口,以及数据驱动的窗口
窗口可以通过灵活的触发条件来定制,以支持复杂的流计算模式。
带反压的连续流模型
数据流应用执行的是不间断的(常驻)operators。
Flink streaming 在运行时有着天然的流控:慢的数据 sink 节点会反压(backpressure)快的数据源(sources)。
容错性
Flink 的容错机制是基于 Chandy-Lamport distributed snapshots 来实现的。
这种机制是非常轻量级的,允许系统拥有高吞吐率的同时还能提供强一致性的保障。
Batch 和 Streaming 一个系统流处理和批处理共用一个引擎
Flink 为流处理和批处理应用公用一个通用的引擎。批处理应用可以以一种特殊的流处理应用高效地运行。
内存管理
Flink 在 JVM 中实现了自己的内存管理。
应用可以超出主内存的大小限制,并且承受更少的垃圾收集的开销。
迭代和增量迭代
Flink 具有迭代计算的专门支持(比如在机器学习和图计算中)。
增量迭代可以利用依赖计算来更快地收敛。
程序调优
批处理程序会自动地优化一些场景,比如避免一些昂贵的操作(如 shuffles 和 sorts),还有缓存一些中间数据。
API 和 类库
流处理应用
DataStream API 支持了数据流上的函数式转换,可以使用自定义的状态和灵活的窗口。
右侧的示例展示了如何以滑动窗口的方式统计文本数据流中单词出现的次数。
val texts:DataStream[String] = ...
val counts = text .flatMap { line => line.split("\\W+") } .map { token => Word(token, 1) } .keyBy("word") .timeWindow(Time.seconds(5), Time.seconds(1)) .sum("freq")
批处理应用
Flink 的 DataSet API 可以使你用 Java 或 Scala 写出漂亮的、类型安全的、可维护的代码。它支持广泛的数据类型,不仅仅是 key/value 对,以及丰富的 operators。
右侧的示例展示了图计算中 PageRank 算法的一个核心循环。
case class Page( pageId: Long, rank:Double) case class Adjacency( id: Long, neighbors:Array[Long])
val result = initialRanks.iterate(30) { pages => pages.join(adjacency).where("pageId").equalTo("pageId") { (page, adj, out : Collector[Page]) => { out.collect(Page(page.id, 0.15 / numPages)) for (n <- adj.neighbors) { out.collect(Page(n, 0.85*page.rank/adj.neighbors.length)) } } } .groupBy("pageId").sum("rank") }
类库生态
Flink 栈中提供了提供了很多具有高级 API 和满足不同场景的类库:机器学习、图分析、关系式数据处理。当前类库还在 beta 状 态,并且在大力发展。
广泛集成
Flink 与开源大数据处理生态系统中的许多项目都有集成。
Flink 可以运行在 YARN 上,与 HDFS 协同工作,从 Kafka 中读取流数据,可以执行 Hadoop 程序代码,可以连接多种数据存储 系统。
部署
Flink可以单独脱离Hadoop进行部署,部署只依赖Java环境,相对简单。
2.Spark Streaming架构及特性分析
2.1 基本架构
基于是spark core的spark streaming架构。
Spark Streaming是将流式计算分解成一系列短小的批处理作业。这里的批处理引擎是Spark,也就是把Spark Streaming的输入数 据按照batch size(如1秒)分成一段一段的数据(Discretized Stream),每一段数据都转换成Spark中的RDD(Resilient Distributed Dataset ) , 然 后 将 Spark Streaming 中 对 DStream 的 Transformation 操 作 变 为 针 对 Spark 中 对 RDD 的 Transformation操作,将RDD经 过操作变成中间结果保存在内存中。整个流式计算根据业务的需求可以对中间的结果进行叠加, 或者存储到外部设备。
简而言之,Spark Streaming把实时输入数据流以时间片Δt (如1秒)为单位切分成块,Spark Streaming会把每块数据作为一个 RDD,并使用RDD操作处理每一小块数据。每个块都会生成一个Spark Job处理,然后分批次提交job到集群中去运行,运行每个 job的过程和真正的spark 任务没有任何区别。
JobScheduler
负责job的调度
JobScheduler是SparkStreaming 所有Job调度的中心, JobScheduler的启动会导致ReceiverTracker和JobGenerator的启动。 ReceiverTracker的启动导致运行在Executor端的Receiver启动并且接收数据,ReceiverTracker会记录Receiver接收到的数据 meta信息。JobGenerator的启动导致每隔BatchDuration,就调用DStreamGraph生成RDD Graph,并生成Job。JobScheduler 中的线程池来提交封装的JobSet对象(时间值,Job,数据源的meta)。Job中封装了业务逻辑,导致最后一个RDD的action被触 发,被DAGScheduler真正调度在Spark集群上执行该Job。
JobGenerator
负责Job的生成
通过定时器每隔一段时间根据Dstream的依赖关系生一个一个DAG图。
ReceiverTracker
负责数据的接收,管理和分配
ReceiverTracker在启动Receiver的时候他有ReceiverSupervisor,其实现是ReceiverSupervisorImpl, ReceiverSupervisor本身启 动的时候会启动Receiver,Receiver不断的接收数据,通过BlockGenerator将数据转换成Block。定时器会不断的把Block数据通会不断的把Block数据通过BlockManager或者WAL进行存储,数据存储之后ReceiverSupervisorlmpl会把存储后的数据的元数据Metadate汇报给ReceiverTracker,其实是汇报给ReceiverTracker中的RPC实体ReceiverTrackerEndpoint,主要。
2.2 基于Yarn层面的架构分析
上图为spark on yarn 的cluster模式,Spark on Yarn启动后,由Spark AppMaster中的driver(在AM的里面会启动driver,主要 是StreamingContext对象)把Receiver作为一个Task提交给某一个Spark Executor;Receive启动后输入数据,生成数据块,然 后通知Spark AppMaster;Spark AppMaster会根据数据块生成相应的Job,并把Job的Task提交给空闲Spark Executor 执行。图 中蓝色的粗箭头显示被处理的数据流,输入数据流可以是磁盘、网络和HDFS等,输出可以是HDFS,数据库等。对比Flink和spark streaming的cluster模式可以发现,都是AM里面的组件(Flink是JM,spark streaming是Driver)承载了task的分配和调度,其他 container承载了任务的执行(Flink是TM,spark streaming是Executor),不同的是spark streaming每个批次都要与driver进行 通信来进行重新调度,这样延迟性远低于Flink。
具体实现
图2.1 Spark Streaming程序转换为DStream Graph
图2.2 DStream Graph转换为RDD的Graph
Spark Core处理的每一步都是基于RDD的,RDD之间有依赖关系。下图中的RDD的DAG显示的是有3个Action,会触发3个job, RDD自下向上依 赖,RDD产生job就会具体的执行。从DSteam Graph中可以看到,DStream的逻辑与RDD基本一致,它就是在 RDD的基础上加上了时间的依赖。RDD的DAG又可以叫空间维度,也就是说整个 Spark Streaming多了一个时间维度,也可以成 为时空维度,使用Spark Streaming编写的程序与编写Spark程序非常相似,在Spark程序中,主要通过操作RDD(Resilient Distributed Datasets弹性分布式数据集)提供的接口,如map、reduce、filter等,实现数据的批处理。而在Spark Streaming 中,则通过操作DStream(表示数据流的RDD序列)提供的接口,这些接口和RDD提供的接口类似。
Spark Streaming把程序中对 DStream的操作转换为DStream Graph,图2.1中,对于每个时间片,DStream Graph都会产生一个RDD Graph;针对每个输出 操作(如print、foreach等),Spark Streaming都会创建一个Spark action;对于每个Spark action,Spark Streaming都会产生 一个相应的Spark job,并交给JobScheduler。JobScheduler中维护着一个Jobs队列, Spark job存储在这个队列中, JobScheduler把Spark job提交给Spark Scheduler,Spark Scheduler负责调度Task到相应的Spark Executor上执行,最后形成 spark的job。
图2.3时间维度生成RDD的DAG
Y轴就是对RDD的操作,RDD的依赖关系构成了整个job的逻辑,而X轴就是时间。随着时间的流逝,固定的时间间隔(Batch Interval)就会生成一个job实例,进而在集群中运行。
代码实现
基于spark 1.5的spark streaming源代码解读,基本架构是没怎么变化的。
2.3 组件栈
支持从多种数据源获取数据,包括Kafk、Flume、Twitter、ZeroMQ、Kinesis 以及TCP sockets,从数据源获取数据之后,可以 使用诸如map、reduce、join和window等高级函数进行复杂算法的处理。最后还可以将处理结果 存储到文件系统,数据库和现场 仪表盘。在“One Stack rule them all”的基础上,还可以使用Spark的其他子框架,如集群学习、图计算等,对流数据进行处 理。
2.4 特性分析
吞吐量与延迟性
Spark目前在EC2上已能够线性扩展到100个节点(每个节点4Core),可以以数秒的延迟处理6GB/s的数据量(60M records/s),其吞吐量也比流行的Storm高2~5倍,图4是Berkeley利用WordCount和Grep两个用例所做的测试,在 Grep这个 测试中,Spark Streaming中的每个节点的吞吐量是670k records/s,而Storm是115k records/s。
Spark Streaming将流式计算分解成多个Spark Job,对于每一段数据的处理都会经过Spark DAG图分解,以及Spark的任务集的调 度过程,其最小的Batch Size的选取在0.5~2秒钟之间(Storm目前最小的延迟是100ms左右),所以Spark Streaming能够满足 除对实时性要求非常高(如高频实时交易)之外的所有流式准实时计算场景。
exactly-once 语义
更加稳定的exactly-once语义支持。
反压能力的支持
Spark Streaming 从v1.5开始引入反压机制(back-pressure),通过动态控制数据接收速率来适配集群数据处理能力.
Sparkstreaming如何反压?
简单来说,反压机制需要调节系统接受数据速率或处理数据速率,然而系统处理数据的速率是没法简单的调节。因此,只能估计当 前系统处理数据的速率,调节系统接受数据的速率来与之相匹配。
Flink如何反压?
严格来说,Flink无需进行反压,因为系统接收数据的速率和处理数据的速率是自然匹配的。系统接收数据的前提是接收数据的Task 必须有空闲可用的Buffer,该数据被继续处理的前提是下游Task也有空闲可用的Buffer。因此,不存在系统接受了过多的数据,导 致超过了系统处理的能力。
由此看出,Spark的micro-batch模型导致了它需要单独引入反压机制。
反压与高负载
反压通常产生于这样的场景:短时负载高峰导致系统接收数据的速率远高于它处理数据的速率。
但是,系统能够承受多高的负载是系统数据处理能力决定的,反压机制并不是提高系统处理数据的能力,而是系统所面临负载高于 承受能力时如何调节系统接收数据的速率。
容错
Driver和executor采用预写日志(WAL)方式去保存状态,同时结合RDD本身的血统的容错机制。
API 和 类库
Spark 2.0中引入了结构化数据流,统一了SQL和Streaming的API,采用DataFrame作为统一入口,能够像编写普通Batch程序或 者直接像操作SQL一样操作Streaming,易于编程。
广泛集成
除了可以读取HDFS, Flume, Kafka, Twitter andZeroMQ数据源以外,我们自己也可以定义数据源,支持运行在Yarn, Standalone及EC2上,能够通过Zookeeper,HDFS保证高可用性,处理结果可以直接写到HDFS
部署性
依赖java环境,只要应用能够加载到spark相关的jar包即可。
3.Storm架构及特性分析
3.1 基本架构
Storm集群采用主从架构方式,主节点是Nimbus,从节点是Supervisor,有关调度相关的信息存储到ZooKeeper集群中。架构如下:
Nimbus
Storm集群的Master节点,负责分发用户代码,指派给具体的Supervisor节点上的Worker节点,去运行Topology对应的组件 (Spout/Bolt)的Task。
Supervisor
Storm集群的从节点,负责管理运行在Supervisor节点上的每一个Worker进程的启动和终止。通过Storm的配置文件中的 supervisor.slots.ports配置项,可以指定在一个Supervisor上最大允许多少个Slot,每个Slot通过端口号来唯一标识,一个端口号 对应一个Worker进程(如果该Worker进程被启动)。
ZooKeeper
用来协调Nimbus和Supervisor,如果Supervisor因故障出现问题而无法运行Topology,Nimbus会第一时间感知到,并重新分配 Topology到其它可用的Supervisor上运行。
运行架构
运行流程
1)户端提交拓扑到nimbus。
2) Nimbus针对该拓扑建立本地的目录根据topology的配置计算task,分配task,在zookeeper上建立assignments节点存储 task和supervisor机器节点中woker的对应关系;
在zookeeper上创建taskbeats节点来监控task的心跳;启动topology。
3) Supervisor去zookeeper上获取分配的tasks,启动多个woker进行,每个woker生成task,一个task一个线程;根据topology 信息初始化建立task之间的连接;Task和Task之间是通过zeroMQ管理的;后整个拓扑运行起来。
3.2 基于Yarn层面的架构
在YARN上开发一个应用程序,通常只需要开发两个组件,分别是客户端和ApplicationMaster,其中客户端主要作用是提交应用程 序到YARN上,并和YARN和ApplicationMaster进行交互,完成用户发送的一些指令;而ApplicationMaster则负责向YARN申请 资源,并与NodeManager通信,启动任务。
不修改任何Storm源代码即可将其运行在YARN之上,最简单的实现方法是将Storm的各个服务组件(包括Nimbus和Supervisor) 作为单独的任务运行在YARN上,而Zookeeper作为一个公共的服务运行在YARN集群之外的几个节点上。
1)通过YARN-Storm Client将Storm Application提交到YARN的RM上;
2)RM为YARN-Storm ApplicationMaster申请资源,并将其运行在一个节点上(Nimbus);
3)YARN-Storm ApplicationMaster 在自己内部启动Nimbus和UI服务;
4)YARN-Storm ApplicationMaster 根据用户配置向RM申请资源,并在申请到的Container中启动Supervisor服务;
3.3 组件栈
3.4 特性分析
简单的编程模型。
类似于MapReduce降低了并行批处理复杂性,Storm降低了进行实时处理的复杂性。
服务化
一个服务框架,支持热部署,即时上线或下线App.
可以使用各种编程语言
你可以在Storm之上使用各种编程语言。默认支持Clojure、Java、Ruby和Python。要增加对其他语言的支持,只需实现一个简单 的Storm通信协议即可。
容错性
Storm会管理工作进程和节点的故障。
水平扩展
计算是在多个线程、进程和服务器之间并行进行的。
可靠的消息处理
Storm保证每个消息至少能得到一次完整处理。任务失败时,它会负责从消息源重试消息。
快速
系统的设计保证了消息能得到快速的处理,使用ZeroMQ作为其底层消息队列。
本地模式
Storm有一个“本地模式”,可以在处理过程中完全模拟Storm集群。这让你可以快速进行开发和单元测试。
部署性
依赖于Zookeeper进行任务状态的维护,必须首先部署Zookeeper。
4.三种框架的对比分析
对比分析
如果对延迟要求不高的情况下,建议使用Spark Streaming,丰富的高级API,使用简单,天然对接Spark生态栈中的其他组 件,吞吐量大,部署简单,UI界面也做的更加智能,社区活跃度较高,有问题响应速度也是比较快的,比较适合做流式的ETL,而 且Spark的发展势头也是有目共睹的,相信未来性能和功能将会更加完善。
如果对延迟性要求比较高的话,建议可以尝试下Flink,Flink是目前发展比较火的一个流系统,采用原生的流处理系统,保证了低延迟性,在API和容错性上也是做的比较完善,使用起来相对来说也是比较简单的,部署容易,而且发展势头也越来越好,相信后面社区问题的响应速度应该也是比较快的。
个人对Flink是比较看好的,因为原生的流处理理念,在保证了低延迟的前提下,性能还是比较好的,且越来越易用,社区也在不断 发展。
一、宝剑露锋芒——Apache Flink作为Apache的顶级项目,Flink固然集众多优点于一身,包括快速、可靠可扩展、完全兼容Hadoop、使用简便、表现卓越。
1.快速快,是Flink的主要特点。利用基于内存的数据流,并将迭代处理算法深度集成到系统的运行时中,这样,Flink使得系统能够以极快的速度处理数据密集型和迭代任务。
2.可靠、可扩展得益于Flink包含自己的内存管理组件、序列化框架和类型推理引擎,所以,即使服务器内存被耗尽,Flink也能够很好地运行。
3.完全兼容Hadoop为什么开发者无需做任何修改,就能利用Flink运行历史遗留的MapReduce操作?这是因为Flink支持所有Hadoop的所有输入/输出格式和数据类型。另外,Flink包括基于Java和Scala的用于批量和基于流数据分析的API、优化器和具有自定义内存管理功能的分布式运行时等,这也是它能够完全兼容Hadoop的原因之一。
4.易用让人感到惊喜的是,在无需进行任何配置的情况下,Flink内置的优化器就能够以最高效的方式在各种环境中执行程序。只需要三个命令,Flink就可以运行在Hadoop的新MapReduce框架Yarn上。
5.表现卓越作为一款优秀的大数据分析引擎,Flink能够利用Java或者Scala语言编写出漂亮、类型安全和可为核心的代码,并能够在集群上运行所写程序。这样,使得开发者可以在无需额外处理的情况下使用Java和Scala数据类型。
一言以蔽之,Apache Flink具有分布式MapReduce一类平台的高效性、灵活性和扩展性,以及并行数据库查询优化方案,同时,它还支持批量和基于流的数据分析,而且提供了基于Java和Scala的API。
总的来说,Flink是一个高效的、分布式的、基于Java实现的通用大数据分析引擎。
二、双锋互切磋——Apache Spark与Apache Flink同样作为流处理引擎,尽管Apache Spark在大数据处理运用中已经十分著名,然而,没有一款工具能够处理所有问题。在一些特殊的情况下,Apache Flink可能很好地弥补了Apache Spark所未能涵盖的地方。那么,应该选哪一款作为企业的大数据分析引擎呢?我们可以通过两者的异同比较,做出最优选择。
相同之处:
1.两者都能提供恰好一次的保证,即每条记录都仅处理一次;
2.与其他处理系统(比如Storm)相比,它们都能提供一个非常高的吞吐量;
3.两者都能够提供自动内存管理;
4.它们的容错开销都非常低。
不同之处:事实上,Apache Spark和Apache Flink的主要差别,就在于计算模型不同。所以,对于选择Apache Spark,还是Apache Flink的问题上,实际上就变成了计算模型的选择。
要了解Apache Spark与Apache Flink的相异之处,首先要对如下三种计算模型有一个初步的理解:
批处理——基本上处理静态数据,一次读入大量数据进行处理并生成输出。
微批处理——结合了批处理和连续流操作符,将输入分成多个微批次进行处理,从根本上讲,微批处理是一个“收集然后处理”的计算模型。
连续流操作符——在数据到达时进行处理,没有任何数据收集或处理延迟。
实际中,Spark采用的是微批处理模型,而Flink采用的是基于操作符的连续流模型。随着数据处理能力的提高,企业开始认识到,信息的价值在数据产生的时候最高,他们希望在数据产生时处理数据,这就是说需要一个实时处理系统。当需要实时处理时,可以优先选择Apache Flink。但也不是所有情况都需要实时系统,这时,Apache Spark则是更优的选择。比如,在电信行业,统计特定用户使用的带宽,微批处理可能是一个更高效的方案。
至于具体应该怎么选,需要企业在延迟、吞吐量和可靠性等多个方面上去进行权衡。
阿里搜索事业部资深搜索专家蒋晓伟将在线分享《阿里流计算和批处理引擎Blink》,其基于Apache Flink项目并且在API和它上兼容,深度分享阿里为了能够满足业务需求在Flink上做的一系列改进。
阿里巴巴在线技术峰会专题:https://yq.aliyun.com/activity/97
峰会统一报名链接:https://yq.aliyun.com/webinar/join/23
蒋晓伟老师,认真而严谨。在加入阿里之前,他曾就职于西雅图的脸书,负责过调度系统,Timeline Infra和Messenger的项目。而后在微软的SQL Server引擎担任过Principal Engineer,负责关系数据库的架构工作。2014年加入阿里以后,作为阿里搜索事业部资深搜索专家,他负责搜索工程的数据团队。
谈起大数据框架,业内尤其对于开源大数据生态圈的许多优秀的计算框架耳熟能详,比如Spark、Hadoop、Storm等。但对于Apache基金会的顶级项目的Flink,知道的都比较有限。而更多是对比Spark,比如知乎的这篇帖子讨论的就是“Apache Flink和Apache Spark有什么异同?它们的发展前景分别怎样?”
为了帮助更多朋友了解Flink,和阿里阿里流计算和批处理引擎Blink。云栖社区特别采访了蒋晓伟。也欢迎关注大数据技术的朋友们多准备问题与蒋晓伟深入交流。
云栖社区:相比Spark、Hadoop、Storm等,是什么样的场景需求让阿里搜索团队选择了Flink?
蒋晓伟:首先我们希望有个流计算和批处理的一体化处理方案。Spark和Flink都具有流和批处理能力,但是他们的做法是相反的。Spark Streaming是把流转化成一个个小的批来处理,这种方案的一个问题是我们需要的延迟越低,额外开销占的比例就会越大,这导致了Spark Streaming很难做到秒级甚至亚秒级的延迟。Flink是把批当作一种有限的流,这种做法的一个特点是在流和批共享大部分代码的同时还能够保留批处理特有的一系列的优化。因为这个原因,如果要用一套引擎来解决流和批处理,那就必须以流处理为基础,所以我们决定先选择一个优秀的流处理引擎。从功能上流处理可以分为无状态的和有状态两种。在流处理的框架里引入状态管理大大提升了系统的表达能力,让用户能够很方便地实现复杂的处理逻辑,是流处理在功能上的一个飞跃。流处理引擎对一致性的支持可以分为:best effort,at least once 和 exactly once。Exactly once的语义才能真正保证完全的一致性,Flink采用的架构比较优雅地实现了exactly once的有状态流处理。另外在保证了一致性的前提下Flink在性能上也是相当优秀的。总结一下,我们觉得在流处理方面Flink在功能,延迟,一致性和性能上综合来看是目前社区最优秀的。所以我们决定采用它来实现流和批的一体化方案。最后,还有一个很重要的原因是Flink有一个比较活跃的社区。
云栖社区:如何看待Flink、Spark、Hadoop、Storm等技术发展和不同场景下的优势对比?比如与Spark相反,Flink把批处理化作流处理,这种方式在使用时是否有什么限制?
蒋晓伟:大数据是从批处理开始的,所以很多系统都是从批处理做起,包括Spark。在批处理上Spark有着较深的积累,是一个比较优秀的系统。随着技术的发展,很多原来只有批处理的业务都有了实时的需求,流处理将会变得越来越重要,甚至成为大数据处理的主要场景。Flink把批当作流来处理有个很重要的优点是如果我们在流中引入一个blocking的算子,我们还能接着做批处理特有的优化,这个是以流处理为基础的计算引擎的一大优势。所以我认为在架构上这种设计在批处理上是可以做到最优的,而且比传统的做法还有一些特别的优势,当然工程上的实现也很重要。
云栖社区:阿里巴巴搜索的流计算和批处理引擎的Blink是基于Apache Flink项目并且在API兼容的。那么在Flink使用过程中有趟过哪些坑?Blink在哪些方面做出了改进?
蒋晓伟:Flink在架构上有很多创新,是非常领先的。但是在工程的实现上有一些不足之处。比如说不同的job的任务可能运行在同一个进程里,这样一个job的问题可能影响其他job的稳定性。Flink的工程实现也不能把集群的资源最合理地利用起来。Blink重新实行了Yarn的结合,完全解决了这些问题。另外Flink是通过checkpoint的机制来保证一致性的,但原有的机制效率比较低,导致在状态较大的时候不可用,Blink大大优化了checkpoint,能够高效地处理很大的状态。稳定性和scalability在生产上都是至关重要的,通过在大集群上的锤炼,Blink解决了一系列这方面的问题和瓶颈,已经成为一个能够支撑核心业务的计算引擎。同时我们扩展了Flink的Streaming SQL层,使得它能够比较完备地支持较复杂的业务。
云栖社区:是否有反馈Flink社区的计划?以及您认为Flink未来的杀手级应用会是什么?
蒋晓伟:我们正在和Flink的发明者Stephan沟通把Blink反馈回Flink社区,这样才能让社区更强大,而社区更强大我们也会更强大。我们计划的第一步是把Blink的Yarn的实现反馈回去,并且抽象出一个支持不同调度系统的方案。接下来会把我们在checkpoint,稳定性,scalability, 可运维性,SQL等方面的改进和优化都陆续反馈回去。我觉得Flink在流计算上的优势是非常大的,随着在线学习等流计算需求的增长,在这方面Flink一定会大放异彩。
云栖社区:从Facebook、微软到阿里,技术开发经验丰富。那么对于技术开发者的成长,有哪些建议或者经验分享?以及推荐一本最喜欢的技术书籍。
蒋晓伟:我觉得在学习中和工作很重要的一点是遇到任何问题一定要刨根问底,不要停留在现象和一些浅层次的直观的原因上,一定要找到本质。一个比较好的判定标志是你能不能一句话给别人讲清楚。要做到这个可能会让你一开始花更多的时间,甚至觉得自己学得比别人慢很多,但是你学过的每个东西都是完全吃透的,而很多东西的原理是相通的,在一段时间的积累后你会发现学任何新东西就像看说明书一样了。书我还真推荐不了,因为我一般是有问题现查,反正是说明书。
下一代大数据计算引擎
自从数据处理需求超过了传统数据库能有效处理的数据量之后,Hadoop 等各种基于 MapReduce 的海量数据处理系统应运而生。从 2004 年 Google 发表 MapReduce 论文开始,经过近 10 年的发展,基于 Hadoop 开源生态或者其它相应系统的海量数据处理已经成为业界的基本需求。
但是,很多机构在开发自己的数据处理系统时都会发现需要面临一系列的问题。从数据中获取价值需要的投入远远超过预期。常见的问题包括:
非常陡峭的学习曲线。刚接触这个领域的人经常会被需要学习的技术的数量砸晕。不像经过几十年发展的数据库一个系统可以解决大部分数据处理需求,Hadoop 等大数据生态里的一个系统往往在一些数据处理场景上比较擅长,另一些场景凑合能用,还有一些场景完全无法满足需求。结果就是需要好几个系统来处理不同的场景。
(来源:https://mapr.com/developercentral/lambda-architecture/)
上图是一个典型的 lambda 架构,只是包含了批处理和流处理两种场景,就已经牵涉到至少四五种技术了,还不算每种技术的可替代选择。再加上实时查询、交互式分析、机器学习等场景,每个场景都有几种技术可以选择,每个技术涵盖的领域还有不同方式的重叠。结果就是一个业务经常需要使用四五种以上的技术才能支持好一个完整的数据处理流程。加上调研选型,需要了解的数目还要多得多。
下图是大数据领域的全景。晕了没?
2018 大数据和 AI 全景
(来源:http://mattturck.com/bigdata2018/)
开发和运行效率低下。因为牵涉到多种系统,每种系统有自己的开发语言和工具,开发效率可想而知。而因为采用了多套系统,数据需要在各个系统之间传输,也造成了额外的开发和运行代价,数据的一致也难以保证。在很多机构,实际上一半以上的开发精力花在了数据在各个系统之间的传输上。
复杂的运维。多个系统,每个需要自己的运维,带来更高的运维代价的同时也提高了系统出问题的可能。
数据质量难以保证。数据出了问题难以跟踪解决。
最后,还有人的问题。在很多机构,由于系统的复杂性,各个子系统的支持和使用落实在不同部门负责。
了解了这些问题以后,对 Spark 从 2014 年左右开始迅速流行就比较容易理解了。Spark 在当时除了在某些场景比 Hadoop MapReduce 带来几十到上百倍的性能提升外,还提出了用一个统一的引擎支持批处理、流处理、交互式查询、机器学习等常见的数据处理场景。看过在一个 Notebook 里完成上述所有场景的 Spark 演示,对比之前的数据流程开发,对很多开发者来说不难做出选择。经过几年的发展,Spark 已经被视为可以完全取代 Hadoop 中的 MapReduce 引擎。
正在 Spark 如日中天高速发展的时候,2016 年左右 Flink 开始进入大众的视野并逐渐广为人知。为什么呢?原来在人们开始使用 Spark 之后,发现 Spark 虽然支持各种常见场景,但并不是每一种都同样好用。数据流的实时处理就是其中相对较弱的一环。Flink 凭借更优的流处理引擎,同时也支持各种处理场景,成为 Spark 的有力挑战者。
Spark 和 Flink 是怎么做到这些的,它们之间又有那些异同,下面我们来具体看一下。
Spark和Flink的引擎技术
这一部分主要着眼于 Spark 和 Flink 引擎的架构方面,更看重架构带来的潜力和限制。现阶段的实现成熟度和局限会在后续生态部分探讨。
数据模型和处理模型
要理解 Spark 和 Flink 的引擎特点,首先从数据模型开始。
Spark 的数据模型是弹性分布式数据集 RDD(Resilient Distributed Datasets)。 比起 MapReduce 的文件模型,RDD 是一个更抽象的模型,RDD 靠血缘(lineage) 等方式来保证可恢复性。很多时候 RDD 可以实现为分布式共享内存或者完全虚拟化(即有的中间结果 RDD 当下游处理完全在本地时可以直接优化省略掉)。这样可以省掉很多不必要的 I/O,是早期 Spark 性能优势的主要原因。
Spark 用 RDD 上的变换(算子)来描述数据处理。每个算子(如 map,filter,join)生成一个新的 RDD。所有的算子组成一个有向无环图(DAG)。Spark 比较简单地把边分为宽依赖和窄依赖。上下游数据不需要 shuffle 的即为窄依赖,可以把上下游的算子放在一个阶段(stage) 里在本地连续处理,这时上游的结果 RDD 可以 省略。下图展示了相关的基本概念。更详细的介绍在网上比较容易找到,这里就不花太多篇幅了。
Spark DAG
(来源:http://datastrophic.io/core-concepts-architecture-and-internals-of-apache-spark/)
Flink 的基本数据模型是数据流,及事件(Event)的序列。数据流作为数据的基本模型可能没有表或者数据块直观熟悉,但是可以证明是完全等效的。流可以是无边界的无限流,即一般意义上的流处理。也可以是有边界的有限流,这样就是批处理。
Flink 用数据流上的变换(算子)来描述数据处理。每个算子生成一个新的数据流。在算子,DAG,和上下游算子链接(chaining) 这些方面,和 Spark 大致等价。Flink 的节点(vertex)大致相当于 Spark 的阶段(stage),划分也会和上图的 Spark DAG 基本一样。
Flink 任务图(来源:https://ci.apache.org/projects/flink/flink-docs-release-1.5/concepts/runtime.html)
在 DAG 的执行上,Spark 和 Flink 有一个比较显著的区别。在 Flink 的流执行模式中,一个事件在一个节点处理完后的输出就可以发到下一个节点立即处理。这样执行引擎并不会引入额外的延迟。与之相应的,所有节点是需要同时运行的。而 Spark 的 micro batch 和一般的 batch 执行一样,处理完上游的 stage 得到输出之后才开始下游的 stage。
在 Flink 的流执行模式中,为了提高效率也可以把多个事件放在一起传输或者计算。但这完全是执行时的优化,可以在每个算子独立决定,也不用像 RDD 等批处理模型中一样和数据集边界绑定,可以做更加灵活的优化同时可以兼顾低延迟需求。
Flink 使用异步的 checkpoint 机制来达到任务状态的可恢复性,以保证处理的一致性,所以在处理的主流程上可以做到数据源和输出之间数据完全不用落盘,达到更高的性能和更低的延迟。
数据处理场景
除了批处理之外,Spark 还支持实时数据流处理、交互式查询和机器学习、图计算等。
(来源: https://databricks.com/spark/about)
实时数据流处理和批处理主要区别就是对低延时的要求。Spark 因为 RDD 是基于内存的,可以比较容易切成较小的块来处理。如果能对这些小块处理得足够快,就能达到低延时的效果。
交互式查询场景,如果数据能全在内存,处理得足够快的话,就可以支持交互式查询。
机器学习和图计算其实是和前几种场景不同的 RDD 算子类型。Spark 提供了库来支持常用的操作,用户或者第三方库也可以自己扩展。值得一提的是,Spark 的 RDD 模型和机器学习模型训练的迭代计算非常契合,从一开始就在有的场景带来了非常显著的性能提升。
从这些可以看出来,比起 Hadoop MapReduce, Spark 本质上就是基于内存的更快的批处理。然后用足够快的批处理来实现各种场景。
(来源:https://www.slideshare.net/ParisCarbone/state-management-in-apache-flink-consistent-stateful-distributed-stream-processing)
前面说过,在 Flink 中,如果输入数据流是有边界的,就自然达到了批处理的效果。这样流和批的区别完全是逻辑上的,和处理实现独立,用户需要实现的逻辑也完全一样,应该是更干净的一种抽象。后续会在深入对比流计算方面的时候做更深入的讨论。
Flink 也提供了库来支持机器学习、图计算等场景。从这方面来说和 Spark 没有太大区别。
一个有意思的事情是用 Flink 的底层 API 可以支持只用 Flink 集群实现一些数据驱动的分布式服务。有一些公司用 Flink 集群实现了社交网络,网络爬虫等服务。这个也体现了 Flink 作为计算引擎的通用性,并得益于 Flink 内置的灵活的状态支持。
总的来说,Spark 和 Flink 都瞄准了在一个执行引擎上同时支持大多数数据处理场景,也应该都能做到这一点。主要区别就在于因为架构本身的局限在一些场景会受到限制。比较突出的地方就是 Spark Streaming 的 micro batch 执行模式。Spark 社区应该也意识到了这一点,最近在持续执行模式(continuous processing)方面开始发力。 具体情况会在后面介绍。
有状态处理(Stateful Processing)
Flink 还有一个非常独特的地方是在引擎中引入了托管状态(managed state)。要理解托管状态,首先要从有状态处理说起。如果处理一个事件(或一条数据)的结果只跟事件本身的内容有关,称为无状态处理;反之结果还和之前处理过的事件有关,称为有状态处理。稍微复杂一点的数据处理,比如说基本的聚合,都是有状态处理。Flink 很早就认为没有好的状态支持是做不好留处理的,因此引入了 managed state 并提供了 API 接口。
Flink 中的状态支持
(来源:https://www.slideshare.net/ParisCarbone/state-management-in-apache-flink-consistent-stateful-distributed-stream-processing)
一般在流处理的时候会比较关注有状态处理,但是仔细看的话批处理也是会受到影响的。比如常见的窗口聚合,如果批处理的数据时间段比窗口大,是可以不考虑状态的,用户逻辑经常会忽略这个问题。但是当批处理时间段变得比窗口小的时候,一个批的结果实际上依赖于以前处理过的批。这时,因为批处理引擎一般没有这个需求不会有很好的内置支持,维护状态就成为了用户需要解决的事情。比如窗口聚合的情况用户就要加一个中间结果表记住还没有完成的窗口的结果。这样当用户把批处理时间段变短的时候就会发现逻辑变复杂了。这是早期 Spark Streaming 用户 经常碰到的问题,直到 Structured Streaming 出来才得到缓解。
而像 Flink 这样以流处理为基本模型的引擎,因为一开始就避不开这个问题,所以引入了 managed state 来提供了一个通用的解决方案。比起用户实现的特定解决方案,不但用户开发更简单,而且能提供更好的性能。最重要的是能更好地保证处理结果的一致性。
简单来说,就是有一些內秉的数据处理逻辑,在批处理中容易被忽略或简化处理掉也能得到可用的结果,而在流处理中问题被暴露出来解决掉了。所以流计算引擎用有限流来处理批在逻辑上比较严谨,能自然达到正确性。主要做一些不同的实现来优化性能就可以了。而用更小的批来模拟流需要处理一些以前没有的问题。当计算引擎还没有通用解决方案的时候就需要用户自己解决了。类似的问题还有维表的变化(比如用户信息的更新),批处理数据的边界和迟到数据等等。
编程模型
Spark 1.6 时的 API 状态
Spark 的初衷之一就是用统一的编程模型来解决用户的各种需求,在这方面一直很下功夫。最初基于 RDD 的 API 就可以做各种类型的数据处理。后来为了简化用户开发,逐渐推出了更高层的 DataFrame(在 RDD 中加了列变成结构化数据)和 Datasets(在 DataFrame 的列上加了类型),并在 Spark 2.0 中做了整合(DataFrame = DataSet[Row])。Spark SQL 的支持也比较早就引入了。在加上各个处理类型 API 的不断改进,比如 Structured Streaming 以及和机器学习深度学习的交互,到了今天 Spark 的 API 可以说是非常好用的,也是 Spark 最强的方面之一。
Spark 2.0 API
(来源:https://databricks.com/blog/2016/07/14/a-tale-of-three-apache-spark-apis-rdds-dataframes-and-datasets.html)
Flink 的 API 也有类似的目标和发展路线。Flink 和 Spark 的核心 API 可以说是可以基本对应的。今天 Spark API 总体上更完备一下,比如说最近一两年大力投入的和机器学习深度学习的整合方面。Flink 在流处理相关的方面还是领先一些,比如对 watermark、window、trigger 的各种支持。
Flink API
(来源:https://ci.apache.org/projects/flink/flink-docs-release-1.5/concepts/programming-model.html)
小结
Spark 和 Flink 都是通用的能够支持超大规模数据处理,支持各种处理类型的计算引擎。两个系统都有很多值得探讨的方面在这里没有触及,比如 SQL 的优化,和机器学习的集成等等。这里主要是试图从最基本的架构和设计方面来比较一下两个系统。因为上层的功能在一定程度上是可以互相借鉴的,有足够的投入应该都能做好。而基本的设计改变起来会伤筋动骨,更困难一些。
Spark 和 Flink 的不同执行模型带来的最大的区别应该还是在对流计算的支持上。最开始的 Spark Streaming 对流计算想得过于简单,对复杂一点的计算用起来会有不少问题。从 Spark 2.0 开始引入的 Structured Streaming 重新整理了流计算的语义,支持按事件时间处理和端到端的一致性。虽然在功能上还有不少限制,比之前已经有了长足的进步。不过 micro batch 执行方式带来的问题还是存在,特别在规模上去以后性能问题会比较突出。最近 Spark 受一些应用场景的推动,也开始开发持续执行模式。2.3 里的实验性发布还只支持简单的 map 类操作。
Spark 持续执行模式状态
(来源:https://www.slideshare.net/databricks/continuous-processing-in-structured-streaming-with-jose-torres)
从最近 Spark+AI Summit 大会上的介绍来看,会发展成一个和 Flink 的流处理模式比较相似的执行引擎。不过从上图来看,主要的功能都还在开发中或者待开发。对将来能做到什么程度,和 Spark 原来的 batch 执行引擎怎么结合,我们拭目以待。
Apache Spark是目前应用最广泛、最流行的大数据计算平台之一,在2.X版本中,Apache Spark已经开始摒弃RDD的数据模型,采用Spark SQL的Dataset作为统一的数据模型来构建更加高效的计算框架。然而,2015年成为Apache顶级项目的Apache Flink却被很多人认为是未来最有可能取代Spark的新一代大数据计算引擎。本文将简单介绍二者的区别以及为什么会有这种说法。
Spark的流行除了本身是一个很优秀的框架外也有一些大数据生态的因素。众所周知,虽然MapReduce框架开启了大数据批处理的时代,但是因为自身的限制导致编程的灵活性受到很大影响,而Spark一开始采用的RDD数据模型则有更加高效灵活的编程方式,并且支持内存计算,这使得Spark更受欢迎。
复杂的Hadoop生态
除此之外,还有个重要的因素是在大数据生态的多样性。之前,包括批处理、实时处理、SQL查询、交互分析等,在大数据生态中都有各自的一套组件,每一个应用场景都有着好几种可替代的技术方案,但正常情况下,实际应用的场景都相对比较复杂,因此,构建一个适合自己业务场景的大数据引擎通常面临着很多的技术方案,不同的方案优缺点不同,因此,构建一个完整的支撑业务场景的大数据引擎也要使用多种种技术,这导致了很多问题:如技术学习曲线陡峭、开发和运行效率低下、运维的困难等。
而Spark从一开始就使用一个统一的引擎进行批处理、流处理、交互分析等,使得应用价值大大提高。
尽管Spark在批处理上有很大优势,但是在流处理方面依然有很大的缺陷。首先,Spark Streaming是准实时的,它处理的方式是微批处理模型。在动态调整、事物机制、延迟性、吞吐量等方面并不优秀。但是由于Spark位于Spark生态中,它可以很好的与其他应用结合,因此使用的人也不少。
然而越来越多的公司发现,很多场景需要对流数据进行处理,流数据处理的价值也越来越高。如网络故障检测、欺诈行为检测等。这些问题使用流处理将有更高的价值。这就是Flink的机会。
Apache Flink是一个分布式处理引擎,用于对无界和有界数据流进行有状态计算。 Flink设计为在所有常见的集群环境中运行,以内存速度和任何规模执行计算。可以说,它为流处理而生。
Apache Spark和Apache Flink的主要差别就在于计算模型不同。Spark采用了微批处理模型,而Flink采用了基于操作符的连续流模型。
Flink 的基本数据模型是数据流,及事件(Event) 的序列。数据流作为数据的基本模型可能没有表或者数据块直观熟悉,但是可以证明是完全等效的。流可以是无边界的无限流,即一般意义上的流处理。也可以是有边界的有限流,这样就是批处理。
而Spark现在也提供了Structured Streaming Programming,目的也是要和Flink竞争,防止被踢出局。同样的,有Spark的经验,Flink也提供了多个基于统一框架的高层次组件。
由于流处理在应用的场景越来越多,而Flink在流处理上的优秀表现使得很多公司也开始采用这个计算引擎。由于Flink也提供了类似Spark的SQL/ML等组件,因此有人认为Flink是下一代大数据计算引擎。然而,随着Spark在流上的处理,也未必见得Flink就能赢。从Google Trends上看二者的趋势,Spark目前仍然远比Flink受欢迎的多。其社区也更加活跃。但Flink的处理方式也有很多值得借鉴的地方。而且阿里巴巴也是Flink社区的活跃者,也在自己的业务上运行Flink,并做了一个基于Flink的Blink框架。值得大家尝试。抛弃Spark?Flink会是下一代大数据计算引擎吗?