Mapreduce: 编程模型,适用于分布式计算 Map: 映射 预处理 Reduce: 化简 聚合 shuffle: 网络间分发 combiner: Map端的reduce partitioner: 分区,默认hash分区 combiner: 适合最大值,最小值 平均值不适用 文件格式和切片的关系: MR的job提交流程: 1、计算Map数和文件切片: Map运行的基本单位,切片数=map数 FileInputFormat中getSplits方法: minSize:1 maxSize:Long.Max_VALUE 确定文件夹下面的所有文件并进行迭代(listStatus方法) 判断文件是否可切割: 1、默认文本文件格式TextInputFormat 2、通过文件后缀的判断,得到文件的压缩编解码器(bzip2可切割) 3、如果文件可切割: 选择(minSize,blockSize,maxSize)中的中间值作为切片大小 ///重点切片算法 2、使用LocalJobRunner的submitJob方法,真正开始提交作业 3、开始Map作业提交: ExecutorService mapService = createMapExecutor(); runTasks(mapRunnables, mapService, "map"); //执行MapTaskRunnables对象的run函数 //map中除了partition、combiner还有sort阶段 使用maptask的runNewMapper方法开始正式的map阶段 1、根据自定义map类名,获得自定义map对象 2、调用Mapper的run函数来运行用户自定义的map方法 //设置相关变量或者参数,一个map只调用一次 setup(context); try { while (context.nextKeyValue()) { //使用while循环调用自定义map的方法 map(context.getCurrentKey(), context.getCurrentValue(), context); } } finally { //清理过程,包括清理一些没用的k-v cleanup(context); } Spill:溢出 //当map中的数据超出内存空间的80%,超出的数据就会被本地化 map端的输出称为ifile:key-len, value-len, key, value shuffle在调用的时候对ifile进行处理 4、通过shuffle进行网络间分发,reduce的调用过程类似于map过程 5、细节:FileInputFormat ====> RecordReader ==> map ===> partition ===> sort ===> combiner ===> shuffle ====> reduce RecordWriter ====> FileOutputFormat FileInputFormat: TextInputFormat =====> createRecordReader ====> LineRecordReader //负责处理文件,定义以行为单位读取和文件类型为UTF-8 通过LineReader中的readDefaultLine来读行 CR //carriage return 回车 LF //line feed 换行 CRLF // 回车换行 /* We're reading data from in, but the head of the stream may be 流的头部可能已经被buffer所缓存 1. 缓冲区中没有换行符,我们需要拷贝所有然后读取另一个缓冲区 2. 在buffer中含有明确的换行符,只需要拷贝即可 3. 在buffer中没有明确的换行符, 比如buffer以回车作为末尾. 我们拷贝内容到回车符为止到字符串中,我们需要观察什么在回车符之后 1)回车符后有换行符,将CR和LF作为一个整体,作为一个整行结尾 2)回车符后没有换行符,用flag来标记,如果恰好在buffer最后,需要观察下一个buffer的字符