• 键值对RDD数据分区


    1、分区介绍

    Spark目前支持Hash分区和Range分区,和用户自定义分区。Hash分区为当前的默认分区。分区器直接决定了RDD中分区的个数、RDD中每条数据经过Shuffle后进入哪个分区和Reduce的个数。说明:只有Key-Value类型的RDD才有分区器,非Key-Value类型的RDD分区的值是None,每个RDD的分区ID范围:0~numPartitions-1,决定这个值是属于那个分区的。
    def main(args: Array[String]): Unit = {
            //1.创建SparkConf并设置App名称
            val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
     
            //2.创建SparkContext,该对象是提交Spark App的入口
            val sc: SparkContext = new SparkContext(conf)
     
            //3 创建RDD
            val pairRDD: RDD[(Int, Int)] = sc.makeRDD(List((1,1),(2,2),(3,3)))
     
            //3.1 打印分区器
            println(pairRDD.partitioner)
     
            //3.2 使用HashPartitioner对RDD进行重新分区
            val partitionRDD: RDD[(Int, Int)] = pairRDD.partitionBy(new HashPartitioner(2))
     
            //3.3 打印分区器
            println(partitionRDD.partitioner)
     
            //4.关闭连接
            sc.stop()
        }
    

    1、Hash 分区

    HashPartitioner分区的原理:对于给定的key,计算其hashCode,并除以分区的个数取余,如果余数小于0,则用余数+分区的个数(否则加0),最后返回的值就是这个key所属的分区ID。
    HashPartitioner分区弊端:可能导致每个分区中数据量的不均匀,极端情况下会导致某些分区拥有RDD的全部数据。

    2、Ranger 分区 

    RangePartitioner作用:将一定范围内的数映射到某一个分区内,尽量保证每个分区中数据量均匀,而且分区与分区之间是有序的,一个分区中的元素肯定都是比另一个分区内的元素小或者大,但是分区内的元素是不能保证顺序的。简单的说就是将一定范围内的数映射到某一个分区内。
    实现过程为:
    第一步:先从整个RDD中采用水塘抽样算法,抽取出样本数据,将样本数据排序,计算出每个分区的最大key值,形成一个Array[KEY]类型的数组变量rangeBounds;
    第二步:判断key在rangeBounds中所处的范围,给出该key值在下一个RDD中的分区id下标;该分区器要求RDD中的KEY类型必须是可以排序的

     

    3、自定义分区

    自定义分区需要混入Partitioner ,并重写其方法实现分区逻辑

    object Spark11_Transformation_partitionBy {
      def main(args: Array[String]): Unit = {
        //获取 SparkConf 并设置应用名称*本地模式
        val conf: SparkConf = new SparkConf().setAppName("Spark").setMaster("local[*]")
        //获取 Spark 上下文对象
        val sc: SparkContext = new SparkContext(conf)
        //键值对RDD
        val rdd: RDD[(Int, String)] = sc.makeRDD(List((1, "scala"), (2, "spark"), (3, "flink"), (4, "java")))
        rdd.mapPartitionsWithIndex {
          (index, data) => {
            println(index + " " + data.mkString(","))
            data
          }
        }.collect().foreach(println)
        /*    2 (3,flink)
            3 (4,java)
            1 (2,spark)
            0 (1,scala)*/
        /**
         * def partitionBy(partitioner: Partitioner): RDD[(K, V)] = self.withScope {
         * if (keyClass.isArray && partitioner.isInstanceOf[HashPartitioner]) {
         * throw new SparkException("HashPartitioner cannot partition array keys.")
         * }
         * if (self.partitioner == Some(partitioner)) {
         * self
         * } else {
         * new ShuffledRDD[K, V, V](self, partitioner)
         * }
         * }
         */
    
        /**
         * 使用 HashPartitioner 进行重分区
         */
        rdd.partitionBy(new HashPartitioner(2))
          .mapPartitionsWithIndex {
            (index, data) => {
              println(index + " " + data.mkString(","))
              data
            }
          }.collect().foreach(println)
        /*    0 (2,spark),(4,java)
            1 (1,scala),(3,flink)*/
    
        rdd.partitionBy(new MyPartitioner(2))
          .mapPartitionsWithIndex {
            (index, data) => {
              println(index + " " + data.mkString(","))
              data
            }
          }.collect().foreach(println)
    
    
        //释放 Spark 上下文对象
        sc.stop
      }
    
    }
    
    /**
     * 自定义分区器
     *
     * @param partitions
     */
    class MyPartitioner(partitions: Int) extends Partitioner {
      //分区数
      override def numPartitions: Int = partitions
    
      /**
       * 分区逻辑
       *
       * @param key
       * @return
       */
      override def getPartition(key: Any): Int = {
        1
      }
    }

  • 相关阅读:
    Nginx 利用 X-Accel-Redirect response.setHeader 控制文件下载
    Nginx 利用 X-Accel-Redirect response.setHeader 控制文件下载
    CentOS6.4 安装OpenResty和Redis 并在Nginx中利用lua简单读取Redis数据
    CentOS6.4 安装Sphinx 配置MySQL数据源
    在线编译
    Java 日期格式化工具类
    CentOS6.4 安装MongoDB
    yum安装高版本mysql(5.5)
    解决Windows Server 2003不认U盘或移动硬盘的问题
    配置tomcat日志分割
  • 原文地址:https://www.cnblogs.com/wdh01/p/16325551.html
Copyright © 2020-2023  润新知