分区器

 

只有key-value类型的rdd才有分区器

1 HashPartitioner 分区方法

HashPartitioner 是通过对 RDD中的key求取hash值,再对hash值对分区数partitions 取余数得到,如果余数<0,那么就取“余数+partitions”,作为该row对应的分区编号。

优点:HashPartitioner 的适用范围更广
缺点:如果大部分key是相同的话将会导致,各partition之间存在数据倾斜的问题,极端情况下,RDD的所有row被分配到了同一个partition中。

2 RangePartitioner

RangePartitioner分区器的主要作用就是:将一定范围内的数映射到某一个分区内,所以它的实现中分界的方法rangeBounds尤为重要

  1. 确定各partition对应的边界,即rangeBounds;
    • 首先,利用 RangePartitioner伴生对象的sketch()方法对input RDD 的每一个 partition进行抽样,抽样方法采取的是水塘抽样(Reservoir Sampling);
    • RangePartitioner伴生对象的**determineBounds()方法获得边界值组成的数组Array[K];
    • Array[K]被赋值给rangeBounds,即各partition对应的边界。
  2. 根据rangeBounds确定分区个数numPartitions
  3. 根据rangeBounds确定 getPartition(key: Any): Int。
优点: 数据更均衡
缺点:分区与分区之间是有序的,也就是说一个分区中的元素肯定都是比另一个分区内的元素小或者大;但是分区内的元素是不能保证顺序的。简单的说就是将一定范围内的数映射到某一个分区内。


3 自定义分区方法

要实现自定义的分区,需要完成如下两步:

  1. 自定义一个 class,比如UDFPartitioner, 该 class 继承 org.apache.spark.Partitioner 类并实现下面4个方法:

    • numPartitions: Int: 总分区数;
    • getPartition(key: Any): Int: 返回给定键对应的分区编号(0 <= 且 <= numPartitions-1)。
    • equals(): Java 判断相等性的标准方法。这个方法的实现非常重要,Spark 需要用这个方法来检查你的分区器对象是否和其他分区器实例相同,这样 Spark 才可以判断两个 RDD 的分区方式是否相同。
    • hashCode() :有一个问题需要注意,当你的算法依赖于 Java 的 hashCode() 方法时,这个方法有可能会 键值对操作返回负数,需要十分谨慎,确保 getPartition() 永远返回一个非负数。
  2. RDDMap[Int, Row]使用自定义分区器进行分区
    RDDMap[Int, Row]是由key-row对组成的,自定义分区器比如UDFPartitioner会根据每个row要被归纳到的partition编号(每个row对应的key计算出)来完成分区。



posted on 2020-09-30 13:46  happygril3  阅读(167)  评论(0)    收藏  举报

导航