我读了HashPartitioner的文档 . 不幸的是,除了API调用之外没有解释太多 . 我假设 HashPartitioner
基于密钥的散列对分布式集合进行分区 . 例如,如果我的数据是这样的
(1,1), (1,2), (1,3), (2,1), (2,2), (2,3)
因此,分区器会将其放入不同的分区,同一个键落在同一个分区中 . 但是我不明白构造函数参数的意义
new HashPartitoner(numPartitions) //What does numPartitions do?
对于上述数据集,如果我这样做,结果会有何不同
new HashPartitoner(1)
new HashPartitoner(2)
new HashPartitoner(10)
那么 HashPartitioner
如何实际工作呢?
3 回答
好吧,让我们让你的数据集更有趣:
我们有六个要素:
没有分区:
和八个分区:
现在让我们定义小助手来计算每个分区的元素数量:
由于我们没有分区器,因此我们的数据集在分区之间均匀分布(Default Partitioning Scheme in Spark):
现在让我们重新分区我们的数据集:
由于传递给
HashPartitioner
的参数定义了我们期望一个分区的分区数:由于我们只有一个分区,因此它包含所有元素:
请注意,shuffle之后的值的顺序是不确定的 .
如果我们使用
HashPartitioner(2)
也一样我们将获得2个分区:
由于
rdd
被密钥数据分区,因此将不再均匀分布:因为有三个键,只有两个不同的值
hashCode
modnumPartitions
,这里没有任何意外:只是为了确认以上内容:
最后用
HashPartitioner(7)
我们得到七个分区,三个非空,每个分区有2个元素:摘要和注释
HashPartitioner
采用一个定义分区数的参数使用
hash
键将hash
函数可能因语言而异(Scala RDD可能使用hashCode
,DataSets
使用MurmurHash 3,PySpark,portable_hash) .在这种简单的情况下,key是一个小整数,你可以假设
hash
是一个标识(i = hash(i)
) .Scala API使用nonNegativeMod来确定基于计算哈希的分区,
如果密钥分布不均匀,则可能会在群集的一部分处于空闲状态时结束
键必须是可清洗的 . 您可以查看A list as a key for PySpark's reduceByKey的答案,了解有关PySpark特定问题的信息 . HashPartitioner documentation突出显示了另一个可能的问题:
在Python 3中,您必须确保散列是一致的 . 见What does Exception: Randomness of hash of string should be disabled via PYTHONHASHSEED mean in pyspark?
哈希分区器既不是单射的也不是满足的 . 可以将多个密钥分配给单个分区,并且某些分区可以保持为空 .
请注意,当与REPL定义的案例类(Case class equality in Apache Spark)结合使用时,当前基于散列的方法在Scala中不起作用 .
HashPartitioner
(或任何其他Partitioner
)随机播放数据 . 除非在多个操作之间重用分区,否则它不会减少要洗牌的数据量 .RDD
是分布式的,这意味着它被分成若干个部分 . 每个分区都可能位于不同的计算机上 . 带有参数numPartitions
的哈希分区器选择以下列方式放置对(key, value)
的分区:准确创建
numPartitions
分区 .将
(key, value)
放在分区中,编号为Hash(key) % numPartitions
HashPartitioner.getPartition
方法将键作为其参数,并返回键所属的分区的索引 . 分区程序必须知道有效索引是什么,因此它返回正确范围内的数字 . 分区数通过numPartitions
构造函数参数指定 .实现返回大致
key.hashCode() % numPartitions
. 有关详细信息,请参阅Partitioner.scala .