一、数值统计模式
1、求最大值、最小值、总值、个数、平均值
案例:给出用户发帖的第一次时间、最后一次时间、评论总数、帖子平均长度 等。
解决:定义一个 类CaculateObj实现 Writable 接口,以用户ID为Key,在Map/Reduce阶段向HDFS写入的是 CaculateObj 对象,这样一个MapReduce 程序可以完成所有操作。
最大值、最小值、总数、个数 可以用Combiner , 平均值不能用Combiner 。
其中均值在Reduce 阶段使用 总值除以个数 来计算。
public class CaculateObj implements Writable{
private int max ;
private int min ;
private int sum;
private int count;
private int average;
private Date firstDate;
private Date lastDate;
@Override
public void write(DataOutput d) throws IOException {
d.writeInt(max);
d.writeInt(min);
d.writeInt(sum);
d.writeInt(count);
d.writeInt(average);
d.writeLong(firstDate.getTime());
d.writeLong(lastDate.getTime());
}
@Override
public void readFields(DataInput di) throws IOException {
this.max = di.readInt();
this.min = di.readInt();
this.sum = di.readInt();
this.count = di.readInt();
this.average = di.readInt();
this.firstDate = new Date(di.readLong());
this.lastDate = new Date(di.readLong());
}
// Getter / Setter
}
2、求中值和均方差
案例:统计用户每天发帖长度的中值和标准差。
解决方法1:以时间 “天”为 Key,map 阶段的Key是天、Value是帖子长度,Reduce 阶段先计算每天发帖的数目,总长度,手动计算得到中值= 顺序为发帖数/2 的那个元素,均值=总长度/个数,均方差 按公式计算。此方法的缺点是内存消耗大。
解决方法2:以时间 “天” 为Key,map 阶段的Key是天、Value是SortedMapWritable(key为帖子长度,value为1) ,在Combiner 阶段写入key是天,Value是SortedMapWritable(key为帖子长度,value为个数),reduce阶段输入的Value就是SortedMapWritable(帖子长度、相同长度的个数) 。此方法的节约内存,减少传输。
二、反向索引模式
根据数据集生成索引,用于快速搜索或数据的富集能力。
案例:给出用户评论数据,在一系列回答问题的id上创建wikipedia的反向索引
解决:很简单。从url中抽出id,map阶段url为key、id为value,reduce 阶段url为key,id拼凑字符串为value。
三、计数器模式
案例:用hadoop自定义计数器统计每个州的用户数。
解决:使用计数器,
- context.getCounter(STATE_COUNTER_GROUP, state) .increment(1);
四、过滤器模式
就是过滤掉不符合要求的记录。
案例:Grep 作为流行的文本过滤工具,对一个文件进行行扫描,匹配指定的样式就输出。我们要在MapReduce中应用正则表达式。
解决:setup方法中取得要使用的正则表达式,在map中简单使用就行,无需reduce。
案例:随机采样。
解决:setup方法中取得采样参数,在map中简单使用就行,无需reduce。
特别的,有高效的布隆过滤器“ BloomFilter。
案例:给出用户评论数据,过滤出绝大多数不包含指定关键词的评论。
解决:使用BloomFilter。
案例:给出用户评论列表,过滤掉声誉不超过1500的用户的评论。
解决:使用BloomFilter。
五、Top ten 模式
案例:问题:给出用户信息数据,根据用户的声誉值输出top ten。
解决:在Map、Reduce 阶段都计算top ten,使用一个容量为10的PriorityQueue。Map阶段的map方法中将数据保存在PriorityQueue中,不写入HDFS,在clean方法中以Null为key,PriorityQueue中用户信息为Value写入HDFS中。Reduce 阶段直接再将数据放入PriorityQueue,循环完成后,以Null为key,PriorityQueue中用户信息为Value写入HDFS中。
六、Distinct 模式
就是去掉重复值。
案例:给出用户评论数据,根据用户id去重。
解决:map阶段以用户Id为key,Null为value写入HDFS;Combine阶段直接输出用户Id;Reduce阶段直接输出用户Id。
七、结构分层模式
把基于行的数据转换成有层次的格式,例如,json xml。
案例:给出用户发帖和评论数据,创建结构化的xml层次结构,将相关的评论嵌套在对应的发帖之内。
解决:两个Map, map1用于处理发帖, map2处理评论。map输出的key均为帖子Id,map1输出的value标记1表示发帖,map2的输出value标记2表示评论。Reduce的时候以帖子id为key,组合所有的发帖、回帖记录为XML。
案例:使用前面例子的输出,执行自关联操作,创建问题帖,回答帖,和评论的层次结构。
解决:
八、分区模式
分区模式是把记录移动到目录里(分片,分区,或箱)。但不关心记录的顺序。
案例:给出用户信息数据,根据一年内最后访问日期分区数据,一年一个大分区。
解决:配置使用自定义的partitioner。不同年份写入不同目录。
九、分箱模式
归档数据集中的每条记录到一个或多个类别。
案例:给出stackOverflow发帖数据,基于hadoop,pig,hive,hbase四个标签分到四个箱。对于文本内容或标题提到hadoop的,放在跟上面不同的箱。
解决:使用MultipleOutputs 。Map阶段的setup方法配置MultipleOutputs ,map方法写入不同目录,clean方法关闭MultipleOutputs 。
十、全局排序
案例:stackOverflow 的用户数据是按账户排序的。而我们希望根据最后访问网站的时间排序。
解决:
十一、混洗
打乱排序,随机合并数据集。
案例:给出大量评论数据,隐藏评论的某些信息:移除id,移除时间。然后随机混洗数据。
解决:map 阶段随机生成key,将评论作为value,则可将顺序弄乱。
十二、表连接
1、Reduce 端连接
案例: 给出用户数据和用户评论数据,把评论所属用户信息关联到评论数据上。
解决:两个Map,一个读入用户数据,一个读入评论数据,以用户Id为key,用值U、C分别标记用户数据和评论数据。在Reduce阶段再进行连接。
2、使用布隆过滤器的Reduce 端连接
可大大减少数据传输。
案例:只对声誉值在1500以上的用户感兴趣。
解决:
3、Map 端连接
案例:给出少量的用户信息数据和一个大的评论数据,用用户数据丰富评论数据。
解决:Setup阶段,从分布式缓存 DistributedCache 读用户数据并存进内存。
4、Hadoop自带的连接
Hadoop本身有CompositeInputFormat 类支持复合join。这种模式的限制类型为:内连接和全外连接。Mapper的输入必须用指定的方式分区和排序,并且每个输入数据集必须分成相同数量的分区。另外,相同的外键必须在两个数据集相同的分区。这通常发生在几个job有相同的reducer个数并输出键也相同,并且输出文件时不能分割的。例如,比hdfs的block小或是一种不支持split的压缩格式。
案例:给出两个大数据集:用户信息和评论数据,使用用户数据丰富评论数据。
解决:使用CompositeInputFormat
5、笛卡尔积
笛卡尔积会使数据集的大小暴增,甚至是一个100万数据的自连接也会产生1万亿条记录。会用掉很多map slot 并运行很长时间,所以要谨慎使用。
案例:给出处理过的stackOverflow 评论数据,根据每对之间的相似单词的数量找出评论之间的相似程度。
解决:笛卡尔积。
十二、Job链
1、Job链
案例:给出stackOverflow 用户发帖数据,把用户分成两部分,根据高于或低于发帖数的平均值。并且丰富用户信息,加上从另一个数据集获得的声誉值,然后输出。
解决:两个MapReduce 程序。
2、并行Job链
并行job链的驱动跟前面例子的相似。唯一大的改进是jobs被并行提交然后监控它们直到完成。
案例:用到前面例子产生的分箱的用户数据,在两个箱上同时跑job计算平均声誉值。
解决:
3、带Shell 的Job链
4、使用 JobControl的Job链
5、Job链合并
案例:给出用户发帖和用户信息数据,根据声誉值在5000上或下分类用户。
6、Job Merging
十三、输入输出模式
1、生成数据模式
案例:为了生成随机stackOverflow数据,我们使用1000个单词的list生成随机短评。我们需要生成一个随机分数,row id,userid,和创建时间。
解决:
2、外部源输出模式
外部源输出模式写到hadoop系统之外。
案例:给出用户信息数据,并行随机分发用户-声誉值的映射数据到一个数量可配置的redis集群。
3、外部源输入模式
这种模式不从hdfs加载数据,而是从hadoop以外系统,例如RDB或web service加载。
案例:给出csv格式redis实例列表,通过可配置的hash并行读取所有数据。
4、分区裁剪模式
案例:指根据文件名配置框架挑选和丢弃的要加载到MapReduce的文件的方式。