经过4个RC版本,Spark 1.4最终还是赶在Spark Summit前发布了,本文简单谈下本版本中那些非常重要的新feature和improvement.
正式引入SparkR
Spark 1.4正式引入了SparkR(可以参见本博客的《Spark官方正式宣布支持SparkR(R on Spark)》介绍),它是一个R API,SparkR是基于Spark的DataFrame抽象。用户可以通过local R data frames或者来自Spark各种外部数据源(比如Hie表)来创建SparkR DataFrame,SparkR DataFrame支持所有Spark DataFrame所支持的操作,包括聚合、过滤、分组、汇总统计以及其他的分析函数。同时它也支持混入SQL查询,而且支持将查询结果保存成DataFrame或者从DataFrame中获取数据。因为SparkR使用的是Spark的并行计算引擎,所以它的操作将可以使用多个Core和机器,而且可以在集群中分析大规模的数据,来看下下面的例子:
01 | people <- read.df (sqlContext, "./examples/src/main/resources/people.json" , "json" ) |
02 | head (people) |
03 | ## age name |
04 | ##1 NA Michael |
05 | ##2 30 Andy |
06 | ##3 19 Justin |
07 |
08 | # SparkR automatically infers the schema from the JSON file |
09 | printSchema (people) |
10 | # root |
11 | # |-- age: integer (nullable = true) |
12 | # |-- name: string (nullable = true) |
关于SparkR的编程指南,可以看这里《SparkR(R on Spark)编程指南》。
Spark Core:
现在大家最关心什么?性能和运维呀! 什么最影响性能?必须shuffle呀!什么是运维第一要务?必须是监控呀(就先不扯alert了)!1.4在这两点都做足了功夫。 1.4中,Spark为应用提供了REST API来获取各种信息(jobs / stages / tasks / storage info),使用这个API搭建个自己的监控简直是分分钟的事情,不止于此,DAG现在也能可视化了,不清楚Spark的DAGScheduler怎么运作的同学,现在也能非常轻易地知道DAG细节了。再来说说shuffle, 大家都知道,从1.2开始sort-based shuffle已经成为默认的shuffe策略了,基于sort的shuffle不需要同时打开很多文件,并且也能减少中间文件的生成,但是带来的问题是在JVM的heap中留了大量的java对象,1.4开始,shuffle的map阶段的输出会被序列化,这会带来两个好处:1、spill到磁盘上的文件变小了 2、GC效率大增 ,有人又会说,序列化反序列化会产生额外的cpu开销啊,事实上,shuffle过程往往都是IO密集型的操作,带来的这点cpu开销,是可以接受。
大家期待的钨丝计划(Project Tungsten)也在1.4初露锋芒,引入了新的shuffle manager “UnsafeShuffleManager”, 来提供缓存友好的排序算法,及其它一些改进,目的是降低shuffle过程中的内存使用量,并且加速排序过程。 钨丝计划必定会成为接下来两个版本(1.5,1.6)重点关注的地方。
Spark Streaming:
Streaming在这个版本中增加了新的UI, 简直是Streaming用户的福音啊,各种详细信息尽收眼底。话说Spark中国峰会,TD当时坐我旁边review这部分的code,悄悄对说我”this is awesome”。对了,这部分主要是由朱诗雄做的,虽然诗雄在峰会上放了我鸽子,但必须感谢他给我们带来了这么好的特性!另外此版本也支持了0.8.2.x的Kafka版本。
窗口函数和DataFrame的其他提升
Spark SQL(DataFrame)
支持老牌的ORCFile了,虽然比Parquet年轻,但是人家bug少啊 : ) 1.4提供了类似于Hive中的window function,还是比较实用的。本次对于join的优化还是比较给力的,特别是针对那种比较大的join,大家可以体会下。JDBC Server的用户肯定非常开心了,因为终于有UI可以看了呀。
1 | val w = Window.partitionBy( "name" ).orderBy( "id" ) |
2 | df.select( |
3 | sum( "price" ).over(w.rangeBetween(Long.MinValue, 2 )), |
4 | avg( "price" ).over(w.rowsBetween( 0 , 4 )) |
5 | ) |
除此之外,社区为DataFrame带来了大量的提升,包括支持丰富的统计和数学函数(看这里《Spark1.4中DataFrame功能加强,新增科学和数学函数》)。
Spark ML/MLlib
ML pipelines从alpha毕业了,大家对于ML pipelines的热情还真的蛮高的啊。我对Personalized PageRank with GraphX倒是蛮感兴趣的,与之相关的是recommendAll in matrix factorization model。 事实上大多数公司还是会在Spark上实现自己的算法。
可视化和监控工具
生成环境下的Spark程序一般都很复杂,而且包含了很多的stages,Spark 1.4.0加入了可视化和监控工具,使得我们在spark作业运行的时候理解Spark的运行,这些都是非常棒的功能!
RestAPI
在Spark 1.4中引入了REST API,这样我们可以像Hadoop中REST API一样,很方便地获取一些信息。这个ISSUE在https://issues.apache.org/jira/browse/SPARK-3644
里面首先被提出,已经在Spark 1.4加入。
Spark的REST API返回的信息是JSON格式的,开发者们可以很方便地通过这个API来创建可视化的Spark监控工具。目前这个API支持正在运行的应用程序,也支持历史服务器。在请求URL都有/api/v1
。比如,对于历史服务器来说,我们可以通过http://:18080/api/v1
来获取一些信息;对于正在运行的Spark应用程序,我们可以通过http://localhost:4040/api/v1
来获取一些信息。
下面是目前Spark支持的所有REST API:
当应用程序运行在YARN模式,每个应用程序将有多个attempts,所以我们需要将上面所有[app-id]
改成[app-id]/[attempt-id]
。上面所有的URL都是有版本的,这样将使得开发者们很容易在上面开发应用程序。此外,Spark还提供以下保证:
1、任何一个版本的Endpoints都不会被移除;
2、单个字段将永远不会从任何的Endpoints中移除;
3、新的Endpoints可能被加入;
4、新的字段可能会被加入到某个Endpoints中;
5、新的版本可能会在未来加入到单独的Endpoint中(比如api/v2
),而且新版本不要求向后兼容;
6、API的版本可能会被删除,但至少存在一个新的API版本。
需要注意的是,即使是想检查正在运行的应用程序UI是,我们也需要加入applications/[app-id]
部分,即使是存在一个应用程序。比如如果你想获取所有正在运行的应用程序的作业列表,你可以通过http://localhost:4040/api/v1/applications/[app-id]/jobs
获取,这样做是为了在两种模式中保存一致的路径。查看:http://www.iteblog.com/archives/1386