写在前面:
在做直播的时候有同学问Spark不是用Scala语言作为开发语言么,的确是的,从网上查资料的话也会看到大把大把的用Scala编写的Spark程序,但是仔细看就会发现这些用Scala写的文章绝大部分是初级内容,最常见的就是某一个API是怎么用的,很多都是拷贝粘贴的重复内容,真正深入的内容并不多见。之前看美团团队写的Spark优化相关放出的代码是用Java写的,《数据算法-Hadoop/Spark大数据处理技巧》这本书里Spark的示例代码也是使用Java语言编写的。所以有理由相信,在大多数企业里做Spark开发时仍然是以Java为主的。
当然,使用Java开发Spark的确代码量比较大,比较繁琐,很多使用Scala能够直接调用的API需要在Java里用几步操作才能完成(比如Scala里的SortByValue,在Java里要先Reverse,再sortByKey,最后在Reverse回来。。。),但是我还是觉得对于水平没那么高的程序员来说,使用Java开发Spark仍然是不错的选择,或者说是最优的选择。
ps:由于测试环境使用的是伪集群,只有一个节点,所以我发实现数据在多节点上的混洗,所以很有有可能当前的运行结果和在真正集群环境下运行是不一样的。多节点集群模式待以后验证。
1.二次排序问题
①推荐使用MapReduce或Spark自带的归约器进行值排序。
MapReduce的二次排序思想是构造2元Key,重写Key的compareTo(),规定排序原则,数据源如下
年 月 日 气温
2012,01,01,5
2012,01,02,45
2000,12,04,20
2000,11,01,20
2000,12,02,-20
2000,11,07,30
2000,11,24,-40
排序后的结果(优先比年月,然后再比温度)
200011,-40 -40,
200011,20 20,
200011,30 30,
200012,-20 -20,
200012,20 20,
201201,5 5,
201201,45 45,
之后通过setGroupingComparatorClass完成按照Key的分组Reduce。
setGroupingComparatorClass决定了Reduce的分组规则。
200011 -40,20,30,
200012 -20,20,
201201 5,45,
这样就完成了对数据的二次排序
②spark的shuffle是基于散列的,因此是没办法直接使用框架完成二次排序的,value的排序只能基于List的Sort。(书里例子是spark-1.1.0,不知道spark2.0以后的版本是否能够实现二次排序)这里的午饭完成二次排序的意思是,无法像MapReduce的例子里一样将Value通过Reduce生成按照排序顺序排列的列表。但是基于RDD的二次排序是可以实现的。
实现的方法是Key类实现Ordered,Serializable两个接口,实现其中的比较方法即可,然后在以此类为Key的PairRDD上调用SortByKey就可以了。