写的不到位的地方,欢迎评论指出不足之处
- MapReduce
- 数据以一条记录为单位,经过map方法映射成 K,V,相同的 key 为一组,这一组数据调用一次 reduce 方法,在方法内迭代计算着一组数据
- 经验
- 数据集一般是用迭代计算的方式
- block (物理切割):split(切片/逻辑切割)
- 注意
- 框架默认的 split 数量 = block 数量
- 控制并行数:由切片数决定
- 切片利用 block 上的 location 信息、副本信息,决定 map 的计算程序移动哪一台计算去(计算向数据移动)
- 情况
- 1:1
- 一块 block 可由一个 split 处理
- N:1
- 多块 block 可由一个 split 处理
- 1:N
- 一块 block 可由多个 split 处理
- 默认副本是3 ,每一个 split 对应一个副本位置,因此并不冲突
- split :map
- 情况
- 1:1
- 一个切片对应一个 map
- 切片中是字节数组,需要格式化出每一条数据
- 格式化条件:人决定
- map(key,value) :reduce
- 注意
- 控制并行数:人决定
- 组不可拆开
- 框架默认的 reduce 数量:1
- 一般根据需求决定
- 参考 K 的各种数量、实际设备数量等
- 在合适的节点上,放合适的进程数,而不是无限放大
- 步骤
- map 以键值对K,V的形式组成
- 由于 K 会有很多种,因此可以增加 reduce 的数量,并行处理,提高处理效率
- reduce 根据自身要处理的数据,会将不同节点上的 map,需要处理 K 的相关数据,合并到一起
- reduce 即使有多个,每一个也需要线形处理
- 情况
- N:1
- 多个 map 可由一个 reduce 处理
- N:N
- 多个 map 可由多个 reduce 处理
- 1:1
- 一个 map 可由一个 reduce 处理
- 1:N
- 多个 map 可由多个 reduce 处理
- group(key):partition
- 情况
- 1:1
- 一个分组对应一个分区
- N:1
- 多个分组对应一个分区
- N:N
- 多个分组对应多个分区
1:N
一个分组只对对应一个分区,其它无作用
- MapTask (线形)
- 一条数据调用一次方法
- input split (切片)
- 格式化出记录,以记录为单位调用 map 方法
- map
- 输出映射成 K,V
- K,V 会参与分区计算,拿 KEY 计算出 P(分区号)
- K,V,P
- 中间数据集
- 无缓冲区时:JVM 每获得一条数据向磁盘写
- I/O会触发调用内核:CPU本应处理JVM内的逻辑代码,若调用I/O,CPU不会读取“我的代码”,会从用户态切换内核态,操作 kernel级别
- kernel里才是真正I/O API调用 native 实际方法
- 由内核读取数据,放到自身缓冲区,再放到磁盘
- 有缓冲区时
- K,V,P 向缓冲区里存储数据
- 当缓冲区满时,再执行系统 I/O 放入磁盘内(一次放入好多数据)
- 在缓冲区数据写入磁盘之前,需要2次排序
- 分区有序,并且分区内的key有序
- 未来相同的一组key会相邻的排在一起
- 归并排序算法:一次文件 I/O
- MapTask 输出
- 会存储在本地磁盘文件系统中
- 最终形成一个文件
- 分区有序
- ReduceTask
- 在 MapTask 输出的文件获取对应的分区号的数据
- 此时数据内部有序外部无序
- 归并排序/全排序
- 一个分区里的组排在一起
- reduce 的归并排序其实可以和 reduce 的方法计算同时发生,尽量减少 I/O
- 只打开文件一次