大数据系统与大规模数据分析 之 作业二
问题描述
作业二:Hadoop编程
- 总体任务
- 输入文件:
- 文本文件
- source destination time 这3个部分由空格隔开
- 其中source和destination为两个字符串,内部没有空格
- time为一个浮点数,代表时间(秒为单位)
- 涵义:可以表示一次电话通话,或表示一次网站访问等
- 输入可能有噪音:如果一行不符合上述格式,应该被丢弃,程序需要正确执行
- mapreduce计算:统计每对source-destination的信息
- 输出:
- source destination count average-time
- 每一个source-destination组合输出一行(注意:顺序相反按不同处理)
- 每行输出通话次数和通话平均时间(保留3位小数,例如2.300)
- 输入文件:
Hadoop编程
MapReduce计算:统计每对source-destination信息
Mapper:
- 输入键值对key-value; 输出中间格式的键值对
- 输出被排序后交给每个Reducer
- Map的个数:由输入大小决定,一般为所有输入文件的总块block数
- combine(): 为了减轻reducer的负担
partition:
- 相当于先对Mapper的结果进行分类,再平均分给Reducer
- 可以默认处理,HashPartitioner
- 默认的取模方式只是为了平均reduce的处理能力
shuffle
- shuffle阶段的主要函数是fetchOutputs(),这个函数的功能就是将map阶段的输出,copy到reduce 节点本地。
Reducer:
- 将一个key关联的一组中间数值集规约reduce到一个更小的数值集
- 三个阶段:
- shuffle:
- Reducer的输入就是Mapper已经排好序的输出
- 框架通过http为每个Reducer获得所有Mapper输出中与之相关的块
- Sort:
- 框架按key对Reducer的输入进行分组
- shuffle和sort两个阶段是同时进行的,map输出也是一边被取回一边被合并
- Secondary sort:中间过程对key的分组规则和reduce对key的规则不同,需要二次排序,控制中间过程的key如何被分组
- Reduce:
- 对已分组的输入数据的每个key-listofvalues调用一次reduce方法
- reduce的个数:0.95或1.75*maximum
- 太少:使节点处于过度负载状态
- 太多:对shuffle过程不利
- shuffle:
思路:
- 直接map + reduce :简单粗暴
- map + combiner + reduce:
- combiner返回Text(),reducer接收进行Text()的切分
- combiner返回自建类型,reducer接收也为自建类型
补充:
- Text:
- 若直接使用 String line=value.toString(); 会输出乱码, 这是由Text这个Writable类型造成的。
- Text类型是String的Writable封装。但其实Text和String还是有些区别,它是一种UTF-8格式的Writable,而Java中的String是Unicode字符。所以直接使用value.toString()方法,会默认其中的字符都是UTF-8编码过的,因而原本GBK编码的数据使用Text读入后直接使用该方法就会变成乱码。
- 正确的方法是将输入的Text类型的value转换为字节数组(value.getBytes()),使用String的构造器String(byte[] bytes, int offset, int length, Charset charset),通过使用指定的charset解码指定的byte子数组,构造一个新的String。
- 如果需要map/reduce输出其它编码格式的数据,需要自己实现OutputFormat,在其中指定编码方式,而不能使用默认的TextOutputForma
- Text: