MapReduce框架 当javaBean作为key时 自定义分组规则一定要将排序字段作为分组的字段 否则分组可能会失效。

以手机流量统计案例举例分析:

原始文件格式:

手机号(phone):       上行流量(upFlow)     下行流量(downFlow)         总流量(sumFlow)

13865424521                100                                100                                        200

13548796531                200                                250                                        450

15387456365                200                                300                                        500

18562465881                100                                350                                        450

14265896452                100                                350                                        450

13865424521                120                                500                                        620

需求:

要求将相同的手机号的数据分为一组将相同手机号的三个流量相加   如上述数据的第一行数据和最后一行数据属于同一手机号 故应该将其合并输出

如下:

13865424521                220                                600                                        820

自定义内容说明:

自定义javaBean: 将上述文件的phone        upFlow        downFlow封装

自定义排序规则:首先按照总流量升序排序   如果总流量一样就按照上行流量升序排序 

自定义分组规则:手机号一样分为一个组

最终输出的数据:

手机号(phone):       上行流量(upFlow)     下行流量(downFlow)         总流量(sumFlow)

13865424521                100                                100                                        200

18562465881                100                                350                                        450

14265896452                100                                350                                        450

13548796531                200                                250                                        450

15387456365                200                                300                                        500

13865424521                120                                500                                        620

由输出的数据可见第一行和最后一行的相同手机号并没有分为一组  而是各自调用了一次reduce方法  故它们的流量没有加在一起  故自定义分组失效 

失效过程演示:

       首先明确一点在MapReduce框架中作为key的一定要实现排序才可以(至于为什么一定要有排序能力才行 见本文末尾补充内容),否则程序无法进行。本文中的key是自己定义的javaBean,那么就一定会实现WritableComparable接口重写里面的comparaTo方法实现自定义排序,再次重申如果javaBean没有实现自定义排序MapReduce程序是无法进行下去的。

redeceTask主动拉取自己分区的数据(如果有分区的话),此时拉到的数据是有序的(按照自定义的排序方法排序的)。数据如下:

<{13865424521,100,100,200} , NullWritable> <{18562465881,100,350,450} , NullWritable> <{14265896452,100,350,450} , NullWritable>

<{13548796531,200,250,450} , NullWritable>  <{15387456365,200,300,500} , NullWritable>  <{13865424521,120,500,620} , NullWritable>

最关键的点来了 reduceTask在进行分组过程是这样的 它是通过判断当前的数据和上一个数据是否是同一类数据 如果是那么它俩就放在一个组如果不是那么就认为前面的是一组的数据,然后会一起去调用一个redece方法。那么它是如何判断两个数据是否是同一类数据呢,这里分两种情况

1)没有自定义分组规则: 前面已经说了一定实现了排序规则 那么排序规则就会兼职分组规则  也就是说comparatTo方法返回0就代表这两个javaBean是同一组的。

2)有自定义分组规则:  那么就按照自定义的规则去判断是否是同一组的。

那么问题就来了  例如上面提到的数据第一条和最后一条根据自定义的分组规则应该是一组的  但是由于排序的缘故是他两被其他数据隔开了,那第一条数据和第二条数据不满足同一组规则  系统就将第一条单独作为一组去调用reduce方法了  而最后一条数据和它的前一条也不满足同一组规则所有最后一条单独调用了一个reduce方法。

总结:

redeceTask拉取到的有序数据的顺序是按照自定义排序得来的   只有连在一起并且满足分组规则的数据才会进入同一组

所有自定义分组字段要与排序字段保持一直。

补充:

1. 为什么作为key一定要有排序能力

因为根据reduceTask的分组规则要求reduceTask拉取到的数据必须是有序的   如果拉取到的数据不是有序的  那么reduceTask就要进行全局的寻找和它同一组的会导致效率极低   但是如果排了序只需要看看后面一个是否同组就可以了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值