MapReduce拾遗

目录

 

 

文章目录

前言

一、MapReduce原理拾遗

 


前言

MapReduce是一种经典的分布式数据处理方法,最近回头再看的时候有一些小知识点将在本文记录整理。


 

一、MapReduce原理拾遗

split和block不是对应关系,前者逻辑概念,后者物理概念,默认情况下相等,为了解耦出现,可以灵活适应cpu密集型和IO密集型计算。

split和map是一一对应关系

group是不能打散到reduce中去的:数据的group(相同的key为一组)不能被破坏

数据以一条记录为单位经过map方法映射成KV,相同的key为一组,这一组数据调用一次Reduce方法,方法内迭代计算一组数据。引申:迭代器设计模式

切片会格式化出记录,以记录为单位调用map方法
map会收到一条记录,map的输出要映射成KV,当map输出KV之后,kv会参与一次计算,这个计算叫做分区计算,拿着key算出P(分区号),最终输出的是K,V,P(因为每条记录要算出它最终要到哪个分区里去)
相同的key,它的P一样。相同的数据为一组,这个组的分区号一定是一个分区,它不能去到别的分区,不能打散。
一个mapTask当中,map处理完切片里的数据之后,会得到输出的一个中间的数据集的状态,这一个map里面的中间的数据是要放在本机的本地的文件目录当中的,并没有输出到hdfs,就拿本机的一个目录来存了,而且要最终存成一个文件。
mapTask的输出是一个文件,存在本地的文件系统中
如果一个mapTask计算了5000条,调起了5000次,那么输出可能也输出了5000条,这5000条要存成一个文件,推算两个成本:map输出一条可以存到文件里去,再输出一条可以存到文件里去,继续向这个文件写,最容易想到的方式,但是这种方式在编程的基本常识里,会有一个问题,JVM里每拿到一条数据就向磁盘写,慢是因为IO会触发调用内核,CPU本来是计算JVM里的逻辑代码的,if判断,变量赋值…但是如果调用IO的话,字符串需要从进程写入磁盘,CPU不会读取代码了,会做用户态到内核态的切换,会切换到内核,操作系统Kernel级别,kernel里面才是真正IO的api调用的native实际的方法。在用Java语言写IO的时候只是调用了api,但是api也不是我们写的,api做了什么事情也不是JVM来写的,JVM调用了统一的内核,任何的进程如果想访问硬件的话,就调一个内核,所有CPU会有一次切换,从用户态切到内核态,这时候由内核读取数据,放到它的缓冲区,然后满了再刷到磁盘去,如果每产生一条数据就去写文件就会很累。
(小故事:住在10层,楼下有小卖部,免费送24瓶啤酒喝,喝啤酒有几种喝法,第一种,从10楼跑到楼下,拿一瓶啤酒,回到家,喝掉它,成本上下往复24次,类比24次系统状态的切换系统调用。第二种,从10楼跑下楼,拿一个箱子装了24瓶啤酒,搬上楼,坐在家里慢慢喝,往复1次,不能在店里喝,因为说的是进程和磁盘,不是一个位置。拿箱子装啤酒就是常说的要使用buffered带缓冲区的IO)
再来看细节:
map输出之后,在内存中动用了一个buffer in memory,但是注意,从map输出的数据已经变成KVP了,这样的数据一条一条的像buffer缓冲区去放,缓冲区默认大小是100M,可以根据数据特征硬件内存大小调整,因为buffer也是在内存的堆里的。
假设buffer满了,可以拿着这个buffer(啤酒箱子)做一次系统IO的调用,把它一股脑写到磁盘去,这个线性操作的过程,只会调用一次系统调用(用户态到内核态的切换)。
可以直接把它写到磁盘,溢写很多次得到很多的小文件,不考虑分区的事情,当map不输出了会有一堆小文件,这些小文件最终可以拼成一个文件,先不想排序的事情,不同的KVP在里面混乱的摆放的。如果只有一个buffer,只有简单的溢写,简单的拼接,这个大文件一定是乱序的 。
当所有map都这样去计算的话 ,所有map都是乱序的。所有map都计算完之后,reduce要拉取了,假设0号分区第一个reduce。这个reduce要去所有map当中拉回属于这个文件当中表示为0号分区(P为0)的记录,如果没有排序,reduce在拉取的时候要估算IO成本了,打开这个文件从第一行遍历到最后一行,把属于0号分区的记录抽出来,一起拉走。因为这个文件是乱序的,所有必须要全局遍历。有几个reduce这个文件就要全量IO访问reduce数量次。
把IO瓶颈解决,就是从程序员到大牛的转变。
如果数据预先排序,数据有序就好做了。
map方法在内存里,buffer在内存里,还没有IO,寻址来说内存是磁盘速度10W倍,如果在产生IO之前,数据都在内存,可以优先在内存动用IO之前做一次快速排序,最简单的可以分区有序。
当这样处理之后,这些小文件有什么特征?
文件内部有序,外部无序。这个时候可以动用归并排序算法,只会对这些文件产生一次IO可以快速得到一个按照分区排好序的文件。
这个时候再来算IO成本,0号reduce只需要打开这个文件,根据0号分区的范围把数据取走,不需要遍历全部IO,前后不需要去读了,IO成本由N变成了1。O(n)变成O(1)了
当reduce拉回来只是分区有序,而分区内无序的数据(只对P做了排序,没有对K做处理),假设这个reduce拉回了两组数据,在结果当中也是乱序的。定义是以一组为单位调用一次reduce方法,处理完之后再处理第二组,1个T的数据假设有两组,每组500G,因为是乱序的,这时候IO成本是2T,在文件大小不变,但是分组变多了,有1000组数据,乱序,时间复杂度1000次1TIO的时间复杂度O(n),n就是有多少组

内存缓冲区溢写磁盘时,做一个2次排序,分区有序,且分区内key有序,未来相同的一组key会相邻的排在一起。会让reduce取去数据,拉取后按照组计算的成本指数级下降,reduce拉过去的小文件又具有了内部有序外部无序,归并成一个文件,全排序O(1)的IO复杂度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值