MapReduce编程:3. 航班数据按月份升序,星期降序排列
题目
- 航空公司数据按月份升序,同时按星期降序排列
- 任意数量的Reducer
- 输出文件全排序:Part-0000,Part-0001,…按文件名依次接将得到一个完整的结果排序
- 输入一下字段逗号隔开:月份,星期几,起飞机场,目的机场
分析
- 题目要求只要实现排序,所以不存在计算的问题,但是要使用两个字段来排序,所以需要自己定义数据类型,来作为map输出的键,而后的起飞机场和目的机场也是需要自己定义数据类型的,所以首先需要了解Writable接口和WritableComparable接口
- 在 https://blog.youkuaiyun.com/Dongroot/article/details/88571680 这篇博客中,我输出了一次中间的处理结果,可以看到,hadoop对自带的类是有默认排序的,所以对于自定义的类,hadoop肯定无法默认排序了,所以需要自己定义排序规则
- 在自定义的数据类型可以进行排序之后,hadoop会根据排序规则去进行排序,这时map和reduce不在需要做别的处理,只需要在map将数据分成键值对,在reduce将结果输出,但是我们要使用多reduce对排序进行并行处理,所以还需要了解Partitioner类
Writable接口和WritableComparable接口
- 在hadoop中,集群环境下,处理数据是在不同的计算机,机器间的数据流通必须要通过网络,所以hadoop提供了Writable接口,来实现数据的序列化与反序列化,这个原理我知道,但是说不清楚,就和做javaweb开发的时候,Javabean要实现Serializable接口一样的道理。所以只要记住,要自己定义数据类型,必须要实现Writable接口
- 同时,MapReduce的输入输出都是键值对形式的,在shuffle阶段,会对键值对根据键的数据类型,进行排序,所以作为键的类,还必须要实现Comparable接口,来定义排序规则
- 所以hadoop提供了WritableComparable接口,实现这个接口,相当于同时实现了Writable和Comparable接口
- Writable接口有两个方法,readFields(DataInput in)和write(DataOutput out),前者是从输入流中抓取数据,重新创建Writable实例,DataInput中的方法可以反序列化java的基本类型;后者是将实例写入到输出流中,DataOutput中的方法可以序列化java的基本类型
- WritableComparable接口多了一个CompareTo(Object o)方法,作用就是定义排序规则,将调用者与参数进行对比,返回值为int型,大于返回大于零的数,等于返回0,小于返回小于零的数
- 还看不懂的话,就没办法了,推荐个博客
https://blog.youkuaiyun.com/chengyuqiang/article/details/78634755
Partitioner类
- 在前面的两个博客中,我都只使用了一个reduce进行操作,很显然没有发挥出MapReduce的全部实力,所以这次我们使用多个reduce进行并行处理,那么问题来了,每个reduce会产生一个输出文件,那么hadoop是如何知道map的结果应该发往哪个reduce进行处理,这就需要指定分区
- hadoop自带了几个Partitioner,在不指定的情况下,hadoop默认使用HashPartitioner,根据哈希算法计算分区,还有一种是TotalOrderPartitioner,分区中的数据范围需要通过分区文件来确认
- 对于TotalOrderPartitioner,分区文件可以自己手动创建,进行等距划分,但是如果数据本身是分布不均匀的,会导致有些reduce工作量大,有些工作量小,所以还可以进行数据抽样,然后根据抽样结果的数据分布,创建分区文件
- 除了这两种Partitioner,还可以自己定义,只要继承Partitioner类,实现ge