跟我一起学Spark之——数据分区

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunWuKong_Hadoop/article/details/86294268

前言

        控制数据分布以获得最少的网络传输可以极大地提升整体性能。

        如果给定RDD只需要被扫描一次(例如大小表join中的小表),我们完全没有必要对其预先进行分区处理,只有当数据集多次在诸如连接这种基于键的操作中使用时(大表),分区才有帮助。

        尽管Spark没有给出显示控制每个键具体落在哪一个工作节点上的方法,但是Spark可以确保同一组的键出现在同一个节点上

例1:使用hash分区将一个RDD分成了100个分区,此时键的哈希值对100取模的结果相同的记录会被放在一个节点上。)

例2:使用范围分区,将键在一定范围区间内的记录都放在一个节点上。)

 1.获取RDD的分区方式

注意:如果要在后续操作中使用partitioned,那就应该在定义partitioned时,在第三行输入的最后加上persist()。

原因:如果不调用persist(),后续的RDD操作会对partitioned整个谱系重新求值,这会导致pairs一遍又一遍地进行哈希分区操作。

import org.apache.spark
import org.apache.spark.{SparkConf, SparkContext}

object rdd_fqfs {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
      .setMaster("local[*]")
      .setAppName("RDD-Join")
    val sc = SparkContext.getOrCreate(conf)
    val pairs =sc.parallelize(List((1,1),(2,2),(3,3)))
    val partitioned = pairs.partitionBy(new spark.HashPartitioner(8)).persist()
    println(partitioned.partitioner)
  }
}

2.从分区中获益的操作

        就Spark1.0而言,能从分区中获益的操作有:cogroup()、groupwith()、join()、leftOuterJoin()、rightOuterJoin()、groupByKey()、reduceByKey()、combinerByKey()、lookup()

        如果两个RDD使用同样的分区方式。并且他们还缓存在同样的机器上(比如一个RDD是通过mapValues()从另一个RDD中创建出来的,这两个RDD就会拥有相同的键和分区方式),或者其中一个RDD还没有倍计算出来,那么跨节点的数据混洗就不会发生了。

3.影响分区方式的操作

        Spark内部知道各操作会如何影响分区方式,并将会对数据进行分区的操作的结果RDD自动设置为对应的分区器。

        列出所有会为生成的结果RDD设好分区方式的操作:cogroup()、groupwith()、join()、leftOuterJoin()、rightOuterJoin()、groupByKey()、reduceByKey()、combinerByKey()、partitionByKey()、sort()、

[mapValues()、flatMapValues()、filter()][这三个-如果父RDD有分区方式的话]

        对于二元操作,如果其中的一个父RDD已经设置过分区方式,那么结果就会采用那种分区方式;如果两个父RDD都设置过分区方式,结果RDD采用第一个父RDD的分区方式。(简单说:一个随父,两个随前父

4.PageRank

        PageRank是一种从RDD分区中获益的执行多次连接的迭代算法。

        可用于对网页排序,也可以用于排序科技文章社交网络中有影响的用户

        计算步骤:

        (1)将每个页面的排序值初始化为1.0

        (2)在每次迭代中,对页面p,向其每个相邻页面(有直接链接的页面)发送一个值为rank(p)/numNeighbors(p)的贡献值

        (3)将每个页面的排序值设为0.15+0.85*contributionsReceived

最后两步会重复几个循环,在此过程中,算法会逐渐收敛于每个页面的实际PageRank值,在实际操作中,收敛需要10个迭代

import org.apache.spark.{HashPartitioner, SparkConf, SparkContext}
object pagerank_test2 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
      .setMaster("local[*]")
      .setAppName("RDD-Join")
    val sc = SparkContext.getOrCreate(conf)
    //假设相邻页面列表以Spark objectFile的形式存储
    val links = sc.objectFile[(String,Seq[String])]("links")
      .partitionBy(new HashPartitioner(100))
      .persist()
    //将每个页面的排序值初始化为1.0;由于使用mapValues,生成的RDD的分区方式会和“links”的一样
    var ranks = links.mapValues(v=>1.0)
    //运行10轮迭代
    for(i <-0 until 10){
      val contributions = links.join(ranks).flatMap{
        case (pageId,(links,rank)) =>
          links.map(dest=>(dest,rank/links.size))
      }
      ranks = contributions.reduceByKey((x,y) => x+y).mapValues(v => 0.15+0.85*v)
    }
    //写出最终排名
    ranks.saveAsTextFile("ranks")
  }
}
import org.apache.log4j.{Level,Logger}
import org.apache.spark.graphx.{Graph, GraphLoader}
import org.apache.spark.{SparkConf, SparkContext}
object pagrank_test3 {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)
    def main(args: Array[String]) {
      val conf = new SparkConf().setAppName("PageRankTest").setMaster("local[2]")
      val sc = new SparkContext(conf)
      val graph = GraphLoader.edgeListFile(sc,"E:\\Users\\11046\\IdeaProjects\\SparkFly\\followers.txt")
      val ranks = graph.pageRank(0.001).vertices
      val users = sc.textFile("E:\\Users\\11046\\IdeaProjects\\SparkFly\\users.txt").
        map {
          line =>
            val fields = line.split(",")
            (fields(0).toLong, fields(1))
        }
      val ranksByUsername = users.join(ranks).map {
        case(id , (username,rank)) => (username,rank)
      }
      println(ranksByUsername.collect().mkString("\n"))
    }
  }

 感谢:

https://blog.csdn.net/a1234h/article/details/77962536《Scala 中 var 和 val 的区别》

https://blog.csdn.net/mmake1994/article/details/79966145《Spark之GraphX案例-PageRank算法与分析》

https://www.jianshu.com/p/27d23bc29914《Spark实现PageRank算法》

5.自定义分区方式

       

猜你喜欢

转载自blog.csdn.net/SunWuKong_Hadoop/article/details/86294268