Map 的流程
原始数据File
·1T数据被切分成块存放在HDFS上,每一个块有128M大小
.数据块Block
. hdfs上数据存储的一个单元,同一个文件中块的大小都是相同的
·因为数据存储到HDFS上不可变,所以有可能块的数量和集群的计算能力不匹配
·我们需要一个动态调整本次参与计算节点数量的一个单位
·我们可以动态的改变这个单位–》参与的节点
切片split
·切片是一个逻辑概念
·在不改变现在数据存储的情况下,可以控制参与计算的节点数目
·通过切片大小可以达到控制计算节点数量的目的
。有多少个切片就会执行多少个Map任务
.一般切片大小为Block的整数倍(21/2)
。防止多余创建和很多的数据连接
·如果Split>Block ,计算节点少了
·如果Split<Block ,计算节点多了
·默认情况下,Split切片的大小等于Block的大小,默认128M
**一个切片对应一个MAPTASK
环形缓冲区
可以循环利用这块内存区域,减少数据溢写时map的停止时间
·每一个Map可以独享的一个内存区域
·在内存中构建一个环形数据缓冲区(kvBuffer),默认大小为100M
·设置缓冲区的阈值为80%,当缓冲区的数据达到80M开始向外溢写到硬盘
·溢写的时候还有20M的空间可以被使用效率并不会被减缓
·而且将数据循环写到硬盘,不用担心OOM问题
分区
根据Key直接计算出对应的Reduce
·分区的数量和Reduce的数量是相等的-
hash(key) 9% partation = num
·默认分区的算法是Hash然后取余
。Object的hashCode()—equals()
。如果两个对象equals,那么两个对象的hashcode一定相等
。如果两个对象的hashcode相等,但是对象不一定equlas
排序
对要褴写的数据进行排序(QuickSort)
·技照先Partation后Key的顺序排序–>相同分区在一起,相同Key的在一起
·我们将来溢写出的小文件也都是有序的
溢写
·将内存中的数据循环写到硬盘,不用担心OOM问题
·每次会产生一个80M的文件
·如果本次Map产生的数据较多,可能会溢写多个文件
拉取fetch
·我们需要将Map的临时结果拉取到Reduce节点
·原则:
。相同的Key必须拉取到同一个Reduce节点
。但是一个Reduce节点可以有多个Key
·拉取数据的时候必须对Map产生的最终的合并文件做全序遍历
。而且每一个reduce都要做一个全序遍历
·如果map产生的大文件是有序的,每一个reduce只需要从文件中读取自己所需的即可
合并Merge
·因为reduce拉取的时候,会从多个map拉取数据
·那么每个map都会产生一个小文件,这些小文件(文件与文件之间无序,文件内部有序)
·为了方便计算(没必要读取N个小文件) ,需要合并文件
·归并算法合并成1个(qishishilia)
·相同的key都在一起
归并Reduce
·将文件中的数据读取到内存中
·一次性将相同的key全部读取到内存中
·直接将相同的key得到结果–>最终结果
写出Output
·每个reduce将自己计算的最终结果都会存放到HDFS上
把一个文件切分成多个block块存放在hdfs上 每个块的大小为128M,
自定义Split(切片)的大小默认切片的大小是128M 手动设置一般是Block的整数倍;
Map开始从对应的切片上读取数据(也就是读取block块的数据)默认读取器每次从block块读取一行数据
当Map内存读取满了时 把Map内存中的数据写入到硬盘中
如果使用io流从Map内存写入硬盘,切块的速度大于Map内存写入硬盘的速度导致map读取读取停滞使运行时间增加
如果使用环形数据缓冲区时 当缓冲区达到80%时(80%可手动调控) 缓冲区剩下的20%继续接收Map内存导出的数据,缓冲区80%导入带硬盘中 加快Map内存写入硬盘中的速度