简单理解MapReudce的分区和分组

分区

简单的说,一组KV交给一组Reduce进行处理,分区就是制订其交付的对应规则。如下代码:

public class DoPartitioner extends HashPartitioner<MyKeyWritable, MyValueWritable>
{
    @Override
    public int getPartition(final MyKeyWritable key, final MyValueWritable value, final int numberPartions)
    {
        return (key.getFirst().hashCode() & Integer.MAX_VALUE) % numberPartions;
    }
}
这是Hash分区最常见的形式了,这里不再累赘。

使用上述分区方法时,发现有时候离散度不够,即有些reduce中总是分不到KV。修改为如下代码:

return (key.getFirst().hashCode() & Integer.MAX_VALUE * 127) % numberPartions;
离散度明显提高了,但是发现修改127为121后,离散度更高。其中缘由暂没有时间研究,暂时作为经验值记录下来吧。

分组

简单地说,分组是指定一组KV只调用一次reduce方法。社区自带的二次排序例子(SecondarySort)中,使用了分组,如下代码:

public static class FirstGroupingComparator implements RawComparator<IntPair> {
@Override
	public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
		return WritableComparator.compareBytes(b1, s1, Integer.SIZE/8, b2, s2, Integer.SIZE/8);
	}

	@Override
	public int compare(IntPair o1, IntPair o2) {
		int l = o1.getFirst();
		int r = o2.getFirst();
		return l == r ? 0 : (l < r ? -1 : 1);
	}
}
示例中key是自定义的IntPair对象,包括了两个成员变量(first和second),但是分组时都只参照第一个成员变量first。

此处注意一个细节问题,假设在reduce方法中有如下代码:

for(IntWritable value: values) {
	context.write(key, value);
}
假设输入数据为(1,2),(1,3),(1,4)。因为具有相同first,所以对这三组KV,reduce方法只被调用一次。但是for循环中,三次的key分别是(1,2),(1,3),(1,4),而不都是(1,2)。

如果不确定一组key是否对应一个分组,可以在分组实现代码中打上调试日志,然后在reduce日志中,应该能看到多个key调用一次reduce方法了......



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值