我使用 Hadoop 全序分区器和随机采样器作为输入采样器。
但是当我增加我的从节点并将任务减少到 8 个时,我收到以下错误:
Caused by: java.io.IOException: Split points are out of order
我不知道这个错误的原因。
如何设置inputsampler.randomsampler
函数的三个参数的数量?
我使用 Hadoop 全序分区器和随机采样器作为输入采样器。
但是当我增加我的从节点并将任务减少到 8 个时,我收到以下错误:
Caused by: java.io.IOException: Split points are out of order
我不知道这个错误的原因。
如何设置inputsampler.randomsampler
函数的三个参数的数量?
两个可能的问题
您可以通过下载分区文件并检查其内容来诊断此问题。分区文件是total.order.partitioner.path
设置或_partition.lst
其他方式的值。如果你的键是文本,你可以跑hdfs dfs -text path_to_partition_file | less
过去看看。这也可能适用于其他密钥类型,但我还没有尝试过。
如果分区文件中有重复的行,则说明您有重复的键,否则您可能使用了错误的比较器。
我最好的猜测是您的键是如此不平衡,以至于分区之间的记录均匀划分会生成具有相同分割点的分区。
要解决此问题,您有多种选择:
a
, a
, b
, c
, c
, c
, d
,e
作为分割点,那么你有 9 个减速器(8 个分割点)和 3 个最大重复项。所以,使用 3 个减速器(3=floor(9/3)),如果你的采样很好,你最终可能会得到正确的分割点。为了完全稳定,如果它有重复的条目,您需要能够重新运行分区步骤,这样您就可以防止偶尔对不平衡键进行过度采样,但在这种复杂程度下,您不妨看看下一个解决方案。num_non_duplicates
)并使用num_non_duplicates+1
减速器。具有重复键的减速器将比其他减速器做更多的工作并且运行时间更长。如果 reduce 操作是可交换和关联的,您可以通过使用组合器来缓解这种情况。确保您mapred.output.key.comparator.class
在调用writePartitionFile
和使用的作业中设置相同TotalOrderPartitioner
Split points are out of order
错误消息来自代码:
RawComparator<K> comparator =
(RawComparator<K>) job.getOutputKeyComparator();
for (int i = 0; i < splitPoints.length - 1; ++i) {
if (comparator.compare(splitPoints[i], splitPoints[i+1]) >= 0) {
throw new IOException("Split points are out of order");
}
}
这条线comparator.compare(splitPoints[i], splitPoints[i+1]) >= 0
意味着如果一对分割点相同或无序,则它们将被拒绝。
1 或 2 个 reducer 永远不会产生此错误,因为分割点不能超过 1 个,并且循环永远不会执行。
你确定你生成了足够的密钥吗?来自 javadoc:TotalOrderPartitioner
输入文件必须使用相同的比较器进行排序并包含
JobContextImpl.getNumReduceTasks() - 1 keys.