鉴于HashPartitioner文档说:
[HashPartitioner]使用Java实现基于散列的分区 是Object.hashCode。
假设我想按DeviceData
分区kind
。
case class DeviceData(kind: String, time: Long, data: String)
通过覆盖RDD[DeviceData]
方法并仅使用deviceData.hashCode()
的哈希码来对kind
进行分区是否正确?
但鉴于HashPartitioner
需要多个分区参数,我很困惑我是否需要事先知道种类的数量以及如果种类多于分区会发生什么?
如果我将分区数据写入磁盘,它会在读取时保持分区吗?
我的目标是致电
deviceDataRdd.foreachPartition(d: Iterator[DeviceData] => ...)
在迭代器中只有DeviceData
个kind
个值。
答案 0 :(得分:8)
使用1
10
2
20
...
A
B
...
做groupByKey
怎么样?或者另一种kind
方法。
在我看来,你并不真正关心分区,只是你在一个处理流程中得到了所有特定的类型?
配对功能允许:
PairRDDFunctions
然而,你可能会更安全一点,比如:
rdd.keyBy(_.kind).partitionBy(new HashPartitioner(PARTITIONS))
.foreachPartition(...)
或rdd.keyBy(_.kind).reduceByKey(....)
或其他一对保证您整体获得作品的功能
答案 1 :(得分:7)
通过覆盖deviceData.hashCode()方法对RDD [DeviceData]进行分区并仅使用类型的哈希码是否正确?
不会。如果您使用Java Object.hashCode
文档,您将找到有关hashCode
的一般合同的以下信息:
如果两个对象根据equals(Object)方法相等,则对两个对象中的每个对象调用hashCode方法必须生成相同的整数结果。
因此,除非纯粹基于kind
设备的平等概念符合您的使用案例,并且我严重怀疑它,修补HashCode
以获得所需的分区是一个坏主意。一般情况下,您应implement your own partitioner,但此处不需要。
由于不包括SQL和GraphX中的特殊方案,partitionBy
仅在PairRDD
上有效,因此创建RDD[(String, DeviceData)]
并使用普通HashPartitioner
deviceDataRdd.map(dev => (dev.kind, dev)).partitionBy(new HashPartitioner(n))
请记住,在kind
具有低基数或使用它进行分区的高度偏斜分布的情况下,可能不是最佳解决方案。