指定自定义分区器不会改变任何事情,因为分区数是提供给分区器的:
int getPartition(KEY key, VALUE value, int numPartitions)
如果您不设置分区器,则使用HashPartitioner。它的实现很简单:
public int getPartition(K key, V value, int numReduceTasks) {
return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}
自定义分区器的设计取决于您。分区器的主要目标是避免偏差并将负载均匀分布在提供的分区数量上。对于一些小工作,可以决定只支持两个减速器,但如果你想让你的工作扩展,那么你必须设计你的工作来运行任意数量的减速器。
或者我必须根据输入的大小来计算和设置reducer的数量以获得最佳性能?
这始终是您必须做的,与自定义分区器的使用无关。您必须设置 reducer 的数量,默认值为 1,Hadoop 不会为您计算此值。
如果您想将停用词发送到一个减速器,而将其他词发送到另一个减速器,您可以执行以下操作:
public int getPartition(K key, V value, int numReduceTasks) {
if (isStopWord(key) {
return 0;
} else {
return ((key.hashCode() & Integer.MAX_VALUE) % (numReduceTasks - 1)) + 1;
}
}
但是它很容易导致大的数据倾斜。第一个减速器将超载,并且比其他减速器需要更长的时间才能完成。在这种情况下,使用两个以上的减速器是没有意义的。
可能是XY problem。我不确定你问的是解决实际问题的最佳方法。