《数据算法-Hadoop/Spark大数据处理技巧》读书笔记(一)——二次排序

写在前面:
在做直播的时候有同学问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就可以了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据算法--HadoopSpark数据处理技巧 data algorithms部分主题⾃写scala程序实现 SecondarySort (chapter 1) data 2015,1,1,10 2015,1,2,11 2015,1,3,12 2015,1,4,13 2015,2,1,22 2015,2,2,23 2015,2,3,24 2015,2,4,25 2015,3,1,20 2015,3,2,21 2015,3,3,22 2015,3,4,23 2015,3,4,23 2015,1,3,12 2015,2,2,23 code import org.apache.spark.sql.SparkSession import org.apache.spark.{Partitioner, SparkConf} class SecondarySortPartitioner(val v: Int) extends Partitioner { override def numPartitions: Int = { v } override def getPartition(key: Any): Int = key match { case (k: String, v: Int) => math.abs(k.hashCode % numPartitions) case null => 0 case _ => math.abs(key.hashCode % numPartitions) } } object SecondarySort { def main(args: Array[String]): Unit = { System.setProperty("hadoop.home.dir", "C:\\winutils-master\\hadoop-2.6.3") val conf = new SparkConf().setMaster("local").setAppName("SecondarySort") val context = SparkSession.builder().config(conf).getOrCreate().sparkContext val rdd = context.textFile("C:\\Users\\IdeaProjects\\spark_learning\\test.txt") val step1 = rdd.map(line => line.split(",")) .map(line => ((line(0) + "-" + line(1), line(3).toInt), line(3).toInt)) val step2 = step1.repartitionAndSortWithinPartitions(new SecondarySortPartitioner(4)) .map { case (k, v: Int) => (k._1, v.toString) }.reduceByKey((x, y) => x + "," + y) step2.foreach(println) } } CommonFriends (chapter 8) data 100,200 300 400 500 600 200,100 300 400 300,100 200 400 500 400,100 200 300 500,100 300 600,100 code import org.apache.spark.{HashPartitioner, SparkConf} import org.apache.spark.sql.SparkSession import scala.collection.mutable.ArrayBuffer object CommonFriends { def main(args: Array[String]): Unit = { System.setProperty("hadoop.home.dir", "C:\\winutils-master\\hadoop-2.6.3") val conf = new SparkConf().setMaster("local").setAppName("CommonFriends") val spark = SparkSession.builder().config(conf).getOrCreate() import spark.implicits._ val context = SparkSession.builder().config(conf).getOrCreate().sparkContext val rdd = context
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值