1、Spark在SQL上的优化,尤其是DataFrame到DataSet其实是借鉴的Flink的。Flink最初一开始对SQL支持得就更好。
2、Spark的cache in memory在Flink中是由框架自己判断的,而不是用户来指定的,因为Flink对数据的处理不像Spark以RDD为单位,就是一种细粒度的处理,对内存的规划更好。
3、Flink原来用Java写确实很难看,现在也在向Spark靠拢,Scala的支持也越来越好。不管怎么说,二者目前都是在相互吸收。
=============================
1、抽象 Abstraction
Spark中,对于批处理我们有RDD,对于流式,我们有DStream,不过内部实际还是RDD.所以所有的数据表示本质上还是RDD抽象。后面我会重点从不同的角度对比这两者。在Flink中,对于批处理有DataSet,对于流式我们有DataStreams。看起来和Spark类似,他们的不同点在于:
(一)DataSet在运行时是表现为运行计划(runtime plans)的
在Spark中,RDD在运行时是表现为java objects的。通过引入Tungsten,这块有了些许的改变。但是在Flink中是被表现为logical plan(逻辑计划)的,听起来很熟悉?没错,就是类似于Spark中的dataframes。所以在Flink中你使用的类Dataframe api是被作为第一优先级来优化的。但是相对来说在Spark RDD中就没有了这块的优化了。
Flink中的Dataset,对标Spark中的Dataframe,在运行前会经过优化。在Spark 1.6,dataset API已经被引入Spark了,也许最终会取代RDD 抽象。
(二)Dataset和DataStream是独立的API
在Spark中,所有不同的API,例如DStream,Dataframe都是基于RDD抽象的。但是在Flink中,Dataset和DataStream是同一个公用的引擎之上两个独立的抽象。所以你不能把这两者的行为合并在一起操作,当然,Flink社区目前在朝这个方向努力,但是目前还不能轻易断言最后的结果。
2、内存管理
一直到1.5版本,Spark都是试用java的内存管理来做数据缓存,明显很容易导致OOM或者gc。所以从1.5开始,Spark开始转向精确的控制内存的使用,这就是tungsten项目了。
而Flink从第一天开始就坚持自己控制内存试用。这个也是启发了Spark走这条路的原因之一。Flink除了把数据存在自己管理的内存以外,还直接操作二进制数据。在Spark中,从1.5开始,所有的dataframe操作都是直接作用在tungsten的二进制数据上。
3、语言实现
Spark是用scala来实现的,它提供了Java,Python和R的编程接口。Flink是java实现的,当然同样提供了Scala API
所以从语言的角度来看,Spark要更丰富一些。因为我已经转移到scala很久了,所以不太清楚这两者的java api实现情况。
4、API
Spark和Flink都在模仿scala的collection API.所以从表面看起来,两者都很类似。下面是分别用RDD和DataSet API实现的word count
// Spark wordcount object WordCount { def main(args: Array[String]) { val env = new SparkContext("local","wordCount") val data = List("hi","how are you","hi") val dataSet = env.parallelize(data) val words = dataSet.flatMap(value => value.split("\\s+")) val mappedWords = (value => (value,1)) val sum = mappedWords.reduceByKey(_+_) println(sum.collect()) } } // Flink wordcount object WordCount { def main(args: Array[String]) { val env = ExecutionEnvironment.getExecutionEnvironment val data = List("hi","how are you","hi") val dataSet = env.fromCollection(data) val words = dataSet.flatMap(value => value.split("\\s+")) val mappedWords = (value => (value,1)) val grouped = mappedWords.groupBy(0) val sum = grouped.sum(1) println(sum.collect()) } }
不知道是偶然还是故意的,API都长得很像,这样很方便开发者从一个引擎切换到另外一个引擎。我感觉以后这种Collection API会成为写data pipeline的标配。
5、Steaming
Spark把streaming看成是更快的批处理,而Flink把批处理看成streaming的special case。这里面的思路决定了各自的方向,其中两者的差异点有如下这些:
实时 vs 近实时的角度:Flink提供了基于每个事件的流式处理机制,所以可以被认为是一个真正的流式计算。它非常像storm的model。
而Spark,不是基于事件的粒度,而是用小批量来模拟流式,也就是多个事件的集合。所以Spark被认为是近实时的处理系统。
Spark streaming 是更快的批处理,而Flink Batch是有限数据的流式计算。
虽然大部分应用对准实时是可以接受的,但是也还是有很多应用需要event level的流式计算。这些应用更愿意选择storm而非Spark streaming,现在,Flink也许是一个更好的选择。
流式计算和批处理计算的表示:Spark对于批处理和流式计算,都是用的相同的抽象:RDD,这样很方便这两种计算合并起来表示。而Flink这两者分为了DataSet和DataStream,相比Spark,这个设计算是一个糟糕的设计。
对 windowing 的支持:因为Spark的小批量机制,Spark对于windowing的支持非常有限。只能基于process time,且只能对batches来做window。而Flink对window的支持非常到位,且Flink对windowing API的支持是相当给力的,允许基于process time,data time,record 来做windowing。我不太确定Spark是否能引入这些API,不过到目前为止,Flink的windowing支持是要比Spark好的。Steaming这部分Flink胜
6、SQL interface
目前Spark-sql是Spark里面最活跃的组件之一,Spark提供了类似Hive的sql和Dataframe这种DSL来查询结构化数据,API很成熟,在流式计算中使用很广,预计在流式计算中也会发展得很快。至于Flink,到目前为止,Flink Table API只支持类似DataFrame这种DSL,并且还是处于beta状态,社区有计划增加SQL 的interface,但是目前还不确定什么时候才能在框架中用上。所以这个部分,Spark胜出。
7、外部数据源的整合
Spark的数据源 API是整个框架中最好的,支持的数据源包括NoSql db,parquet,ORC等,并且支持一些高级的操作,例如predicate push down。Flink目前还依赖map/reduce InputFormat来做数据源聚合。这一场Spark胜
8、Iterative processing
Spark对机器学习的支持较好,因为可以在Spark中利用内存cache来加速机器学习算法。但是大部分机器学习算法其实是一个有环的数据流,但是在Spark中,实际是用无环图来表示的,一般的分布式处理引擎都是不鼓励试用有环图的。但是Flink这里又有点不一样,Flink支持在runtime中的有环数据流,这样表示机器学习算法更有效而且更有效率。这一点Flink胜出。
9、Stream as platform vs Batch as Platform
Spark诞生在Map/Reduce的时代,数据都是以文件的形式保存在磁盘中,这样非常方便做容错处理。Flink把纯流式数据计算引入大数据时代,无疑给业界带来了一股清新的空气。这个idea非常类似akka-streams这种。成熟度目前的确有一部分吃螃蟹的用户已经在生产环境中使用Flink了,不过从我的眼光来看,Flink还在发展中,还需要时间来成熟。
结论
目前Spark相比Flink是一个更为成熟的计算框架,但是Flink的很多思路很不错,Spark社区也意识到了这一点,并且逐渐在采用Flink中的好的设计思路,所以学习一下Flink能让你了解一下Streaming这方面的更迷人的思路。
====================================
Flink 比Spark好的地方:
Stream给力,市面上最好的stream framework没有之一
Stream 近似 Batch没有硬伤(相反mini batch近似Stream会搞乱batch里的顺序)。相当于自带lambda architecture
Flink不足的地方:
用户群没有Spark多,stackoverflow上能找到的Solution少
Documentation还在完善中,尤其scala部分
java比scala啰嗦...
========================================
flink是一个类似spark的“开源技术栈”,因为它也提供了批处理,流式计算,图计算,交互式查询,机器学习等。
flink也是内存计算,比较类似spark,但是不一样的是,spark的计算模型基于RDD,将流式计算看成是特殊的批处理,他的DStream其实还是RDD。而flink吧批处理当成是特殊的流式计算,但是批处理和流式计算的层的引擎是两个,抽象了DataSet和DataStream。
flink在性能上也标新很好,流式计算延迟比spark少,能做到真正的流式计算,而spark只能是准流式计算。而且在批处理上,当迭代次数变多,flink的速度比spark还要快,所以如果flink早一点出来,或许比现在的Spark更火。
=======================================
Spark底层对待每个时间窗口就像对待文件,只不过这些文件允许放一部分或者全部在内存里,在内部实现是对不可变数据集的操作,所有操作都是基于scan
优点是只要基于map reduce封装出来的算子在streaming上基本上都可以用
缺点是Spark里RDD的生成和消费成本太高,没法做到毫秒级,秒级相对来说rdd自身开销也占了不小,但是如果是分钟级,小时级,rdd自身开销相对来说不大了,这个时候spark的吞吐量优势就出来了
Flink底层和Storm差不多,流进来直接更新内部状态,在内部实现状态是允许随时更新的,操作就像个hashmap,你丢什么东西进去都可以,每来一条数据更新一次状态,然后根据你输出的策略定时去获取这些状态输出
由于flink里创建状态和更新状态的成本都很小,所以毫秒级之类的不在话下,你自己写个也差不多的性能
优点是对于秒级以下的处理吞吐量和实时性要比spark高
缺点的话也挺多的
1.因为是基于状态的计算,所以在几个窗口内做做排序什么的很难实现,只能把所有状态丢到内存里你自己做实现,超出内存了估计就直接oom了,spark因为是基于rdd的可以利用rdd的优势,哪怕数据超出内存一样算,所以在较粗时间粒度极限吞吐量上spark streaming要优于flink
2.spark streaming提供的reduceByWindow函数支持一个inverse reduce函数,比如你计算最近1小时,按秒级别窗口滑动,spark通过实现inverse reduce函数每次只计算进来和要逐出的子窗口,flink没提供任何这种相关的api,你就必须要执行3600个窗口的聚合操作,当然这个通过自己封装聚合算子还是能实现的。
共同学习,写下你的评论
评论加载中...
作者其他优质文章