【迁移】Flink vs Spark

用户头像
罗琦
关注
发布于: 2020 年 05 月 22 日

 前几周我出于好奇花了一些时间研究了下flink。当我一看到标准示例就立刻发现他和Spark其中一个例子很像。于是我认为这只是模仿实现了spark功能的另一个框架。但是随着我研究的深入,越来越清晰地发觉,有些藏匿在这个看起来很相似的API后的一些新颖的想法使得flink区别于spark。我被这些想法吸引了,并且花越来越多的时间搞懂和探索。



        许多flink的想法像自定义内存管理,dataset API都已经在Spark中实现了,并且被证明是很不错的。所以搞明白flink可以帮助我们搞清楚未来分布式数据处理方面的趋势信息。



        在这篇博客中我尝试作为一名spark开发者来阐述我对于Apche flink的第一印象。这个审视是我作为一名从事Spark开发2年而仅花了2-3周的时间玩了玩Apache flink的人的一些个人见解。所以带着批判的思维看待我现在做的事吧~



        什么是Apache Flink?



        Apache Flink是新一代的大数据处理引擎,他致力于统一不同数据载入。他听起来像是Apache Spark吗?确实是。Flink尝试去定位Spark尝试去解决的课题。这两个系统都是向着建立单一平台,在这个平台上可以运行诸如批处理,流式,交互计算,图计算,机器学习等。所以flink和Spark的思想体系是很接近的。但是他们在实现的细节方面有着很大的区别。                



        Apache Spark VS Apache Flink



        1  抽象概念



        在Spark里,我们使用RDD抽象模型来运行批处理,使用DStream来创建流计算任务,这些都是RDD本身带有的。所以我们在Spark中展示的所有的数据都使用了RDD。



        在flink中,我们使用Dataset抽象模型来运行批处理,使用DataStreams创建流应用。他们听起来比较像RDD和DStreams但其实不同。不同点表现在:



  • Dataset作为运行时的计划体现



        在spark中RDD在运行时阶段被当作java对象。通过Tungsten的介绍,他的变化是微乎其微的。而Apache flink的Dataset是作为逻辑计划执行的。听着熟悉吗?是的,他们就像是Spark中的dataframes。所以在flink中你可以将Dataframe像API一样使用,作为使用优化器优化过的一等类公民。但是在Spark RDD中没有任何这样的优化存在。



        flink里的Dataset就像是在执行前优化了的Spark Dataframe API。



        在spark 1.6中,dataset API才加入spark,这也将会最终取代RDD。



  • Dataset和DataStream是独立的API



        在Spark中像DStream和Dataframe都是建立在RDD抽象基础之上的。但是在flink中,Dataset和DataStream是建立在



        我们不能将DataSet和DataStreams结合起来,像RDD和DStreams一样。



        故即使flink和spark拥有差不多的抽象组件,他们的实现还是有很大差异的。



        2  内存管理



        直到spark1.5,Spark才开始使用Java堆来缓存数据。尽管对于一个项目来说很容易开始,但结果不是报OOM错误就是gc停止了。所以自从1.5以来,spark步入自定义内存管理阶段,这个项目叫做tangsten。



        Flink总有一天也会自定义内存管理。实际上他还是Spark往这个方向迈进的一个灵感。不仅flink将他的数据存储在自定义的二进制格式中,他直接操作二进制数据。在spark中,自从1.5开始,所有的dataframe操作都是直接在tungsten二进制数据中执行的。



        在JVM上的自定义内存管理有更好的表现和更好的资源利用率。



        3  实现语言



        Spark是用Scala实现的。他也提供其他语言的APIs,这些语言有Java,Python和R。而Flink是用Java实现的。他有提供Scala的API。



        所以语言方面的选择Spark要优于flink。虽然在一些flink的scala API里,是用java实现的抽象。我认为当有更多用户的时候这一点将会得到改善。我对于Spark和Flink中的java API没有太多想法,因为我早已经转向了Scala。



        4  API



        Spark和Flink有着相似的scala集合API。所以从表面上看两个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 = words.map(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 = words.map(value => (value,1))

val grouped = mappedWords.groupBy(0)

val sum = grouped.sum(1)

println(sum.collect())
}

}



我不是很确定,这到底是巧合还是故意的,有着这么相似的API有助于在两个框架中轻易地切换。好像在不久的将来集合API将会成为创建数据通道的标准API。甚至是Scala的发明人,Martin Odersky都认同了这个事实。



        5  流



        Apache Spark将流视为快速的批处理工具。而Apache flink将批处理视为流处理的特殊情形。 这两种都有着优雅的实现方式。不过两种接近的实现的不同点在于



  • 实时VS准实时



        Apache flink提供基于事件的处理,也叫做实时流处理。这很像Storm模型。



        而在Spark中我们提供的最小批量处理不支持切分到事件级别粒度。这种成为准实时。



        Spark Streaming是更快的批处理,Flink批处理绑定在流处理中。



        尽管准实时系统没什么毛病,还是有些系统需要基于事件的实时处理的。这些系统更适合用storm而不是Spark Streaming。这两者之间flink有非常有趣的选择。



  • 结合历史数据和流的能力



        将流处理当作更快的批处理的一点好处在于,我们可以在两种情形之间做相同的抽象。Spark在结合批和流数据上有着极佳的支持因为RDD抽象模型。



        在flink中,批和流不共享同样的api抽象层。所以即使有途径结合基于数据流的历史文件,但他没有Spark来的那么简洁。



        在许多应用中这种能力还是很重要的。在这些应用中Spark代替了Flink流的地位。



  • 多样的窗口函数



        由于最小批的特性,Spark中对窗口函数的支持比较局限,直到现在。你只能在基于处理时间中将批进行窗口化。



        相比于其他系统Flink提供了丰富的窗口系统。窗口函数也是flink流API的重中之重。他提供基于处理时间,数据时间,空记录等的窗口函数。这个多样性使得flink流API相比于spark要强大的多。



        我不确定将这样的API带给Spark会不会很容易,不过直到现在flink有着相比Spark streaming更加有优势的窗口API。



        SQL interface



        目前来看Spark库中最热门的当属spark-sql了。Spark不仅提供了像查询语言一样的Hive,还有用来查询结构数据的DSL一样的Dataframe。这是成熟的API并且在批处理和流世界中广泛地应用。



        现在Flink的Table API只支持像DSL的dataframe,它仍然在beta阶段。据称有计划将sql接口加进去,但是不确定什么时候能够落地到框架中。



        所以现在Spark相比于flink有着不错的sql支持。我认为flink会后来居上的。



        Data source Integration



        Spark数据源API是这个框架中最好的API了。数据源API使得像NoSQL数据库,parquet,ORC这些不错的数据源作为spark中的第一等公民。当然这个API提供了像在源码级别中预测的操作的能力。



        Flink还是很依赖于map/reduce inputFormat去做数据源的集成。尽管他是足够好的推送数据的API,但是它不能充分利用好源的能力。所以flink在数据源集成方面落后了一些。



        Iterative processing



        Spark的一个最经常被谈论到的特征就是高效处理机器学习的能力。由于可以进行内存计算,和其他的一些实现细节,以至于它确实是实现ML算法的强大平台。



        尽管ML算法在spark中是表现为直接非周期图的循环数据流。正常的没有分布式处理系统鼓励去做复杂的循环数据流运算。



        不过flink和其他框架比起来也没有多大差别。他支持在运行时控制循环依赖的图计算。相比于DAG他用了非常搞笑的方式去表现ML算法。所以Flink支持在本地平台的迭代。结果是相比于DAG的方法他更具备可扩展性和高性能。



        我希望spark也能开始在框架中支持这个,这将会大大促进ML协会的发展。



        Stream as platform vs Batch as Platform



        结论



        最后总结下,Spark是更加成熟和完善的框架相比于Flink来说。但是flink带来了譬如自定义的内存管理,像表一样的data set API这些奇妙的想法。Spark协会认识到这点,并且把他应用到spark中。这么看来flink是推动了大数据处理向下一个层次的发展。所以了解flink API和内在的机制可以帮助你了解在技术落地到Spark之前的这个新的流计算范例。

发布于: 2020 年 05 月 22 日 阅读数: 123
用户头像

罗琦

关注

后浪 2017.12.15 加入

字节跳动工程师

评论

发布
暂无评论
【迁移】Flink vs Spark