1.hadoop运行原理
MapReduce
HDFS 分布式文件系统(HDFS客户端的读写流程)
写:
客户端接收用户数据,并缓存到本地
当缓存足够一个HDFS大小的时候
客户端同NameNode通讯注册一个新的块
注册成功后 NameNode给客户端返回一个DateNode的列表
客户端向列表中的第一个DateNode写入块
收到所有的DateNode确认信息后,客户端删除本地缓存
客户端继续发送下一个块
重复以上步骤 所有数据发送完成后,写操作完成
读:
客户端与NameNode通讯获取文件的块位置信息,包括块的所有冗余备份的位置信息:DateNode列表
客户端获取文件位置信息后直接同有文件块的DateNode通讯,读取文件
如果第一个DateNode无法连接,客户端将自动联系下一个DateNode
如果块数据的校验值出错,则客户端需要向NameNode报告,并自动联系下一个DateNode
客户端的hadoop环境:与集群的hadoop包一样
集群入口:core-site.xml、fs.default.name
缓存块大小:fs.block.size
存多少份:fs.replication
2.mapreduce的原理
mapreduce的原理:一个MapReduce框架由一个单独的master JobTracker和集群节点每一个slave TaskTracker共同组成。master负责调度构成一个作业的所有任务,在这些slave上,master监控它们的执行,并且重新执行已经失败的任务。而slave仅负责执行由maste指派的任务。
3.Mapreduce数据倾斜是什么意思?怎么处理?
Mapreduce数据倾斜是指我们在分片的时候导不同分片上的数据不均,导致这些分片在并行处理的时候,有的分片执行事件过长,有的执行时间过短,导致总的执行时间过长的一种现象,通常是由:1.map端的key值过多或者有空值;2.业务本身的特性;3.某些sql就有数据倾斜;4.建表的时候考虑不周等原因造成的。
处理:1.如果是大量数据的时候可以做基于map的key值离散。通过写一个for循环给过多的key打标签。
2.数据量小的时候,且输入的结果不会影响到reduce输入的结果,且不做平均值的时候,用基于map端之后shuffle端之前的reduce操作。
4.combiner的作用,使用时机?
Combiner其实也是一种reduce操作,是map运算的后续操作,在map后续对于相同key值做一个简单合并,减小后续的reduce的计算压力。
数据量小的时候,且输入的结果不会影响到reduce输入的结果,且不做平均值的时候,用基于map端之后shuffle端之前的reduce操作。
5.MapReduce–如何设置Reducer的个数
1.在代码中通过:JobConf.setNumReduceTasks(Int numOfReduceTasks)方法设置reducer的个数;
2.在hive中:set mapred.reduce.tasks;
3.reducer的最优个数与集群中可用的reducer的任务槽数相关,一般设置比总槽数微少一些的reducer数量;Hadoop文档中推荐了两个公式:
0.95*NUMBER_OF_NODES*mapred.tasktracker.reduce.tasks.maximum
1.75*NUMBER_OF_NODES*mapred.tasktracker.reduce.tasks.maximum
备注:NUMBER_OF_NODES是集群中的计算节点个数;
mapred.tasktracker.reduce.tasks.maximum:每个节点所分配的reducer任务槽的个数;
6.MR的过程:
input —–>spilt—–>map—–>combiner—–>shuffer—> partition—–>reduce—–>output
spilt :对数据进行split分片处理,产生K1值和V1值,传给map
map: 数据整理,把数据整理成K2和V2,
combiner:如果map输出内容比较多,reduce计算比较慢,我们可以加个combiner
map端的本地化reduce,减少map输出;
shuffer:相同的数据放到一个分区
partiton:如果reduce不是一个,shuffler做一个分区,将相同的K值,分到一个区;
排序方式:hash方式;
reduce:shuffer分区结束后交给reduce进行计算,形成K3 V 3
output: 将reduce处理完的 K3和V3交给output输出;
a. 客户端编写好mapreduce程序,提交job到jobtracker;
b. Jobtracker进行检查操作,确定输出目录是否存在,存在抛出错误;
c. Jobtracker根据输入计算输入分片input split、配置job的资源、初始化作业、分配任务;
d. 每个input split创建一个map任务,tasktracker执行编写好的map函数;
e. Combiner阶段是可选的,它是一个本地化的reduce操作,合并重复key的值;
f. Shuffle一开始就是map做输出操作,并对结果进行排序,内存使用达到阀值就会spill,把溢出文件写磁盘,写磁盘前有个排序操作,map输出全部做完后,会合并溢出文件,这个过程中还有个Partitioner操作,一个partitioner对应一个reduce作业,reduce开启复制线程,复制对应的map输出文件,复制时候reduce还会进行排序操作和合并文件操作
g. 传输完成,执行编写好的reduce函数,结果保存到hdfs上。
7.MR怎么处理小文件:
1.输入过程合并处理:1.在linux 10000个文件上传到HDFS时候,用脚本形成二进制文件流上传,上传的过程中就合并成了一个文件。
2.如果在hdfs中有大量小文件,首先进行清洗,把10000个小文件清洗成一个文件或者几个文件,写个map(1.前提10000小文件格式相同,2.不会有太多的小文件 一千万个小文件,首先会在操作系统上传时就处理完了,但是要是问可以说,分批做,每一万个存储到一个目录中,对一个目录进行map清洗)),其次,进行reduce计算
清洗会产生数据倾斜: 很多小文件是数据倾斜(解决方法):2.1.基于map端的离散方法;2.2.combiner;
//hdfs为什么怕很多小文件:因为很多小文件的话也会占用namenode目录树的空间,一般一个文件的元数据会占到150字节;而NameNode是要接收集群中所有的DataNode的心跳信息,来确定元数据的信息变化的,当小文件一旦过多,namenode的元数据读取就会变慢。(在HDFS中,namenode将文件系统中的元数据存储在内存中,因此,HDFS所能存储的文件数量会受到namenode内存的限制)
8.如何从编程的角度讲解MR的过程
对数据进行底层默认分片把数据解析成k1/v1形式传给map;
Map对k1/v1进行截取、运算等操作生成k2/v2传给reduce;
Reduce对相同key的值进行计算,生成最终结果k3/v3输出
9.MR中有没有只有Map的
有,只对数据进行分片,解析成key/value形式后,直接输出结果不进行reduce端的去重和数组化的。
eg:比如说我把所有的经过split(map)形成的元素都放到context的key做标签就不会用到reduce。
10.Map输出端的组成部份
Combiner、shuffle、partitioner
11.如何用MR实现join
1) reduce side join(在reduce端做join操作)
在map阶段,map函数同时读取两个文件File1和File2,为了区分两种来源的key/value数据对,对每条数据打一个标签 (tag),比如:tag=0表示来自文件File1,tag=2表示来自文件File2。即:map阶段的主要任务是对不同文件中的数据打标签。
在reduce阶段,reduce函数获取key相同的来自File1和File2文件的value list, 然后对于同一个key,对File1和File2中的数据进行join(笛卡尔乘积)。即:reduce阶段进行实际的连接操作。
2) map side join(在map端做join操作)
之所以存在reduce side join,是因为在map阶段不能获取所有需要的join字段,即:同一个key对应的字段可能位于不同map中。Reduce side join是非常低效的,因为shuffle阶段要进行大量的数据传输。
Map side join是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task内存中存在一份(比如存放到hash table中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table中查找是否有相同的key的记录,如果有,则连接后输出即可。为了支持文件的复制,Hadoop提供了一个类DistributedCache,使用该类的方法如下:
(1)用户使用静态方法DistributedCache.addCacheFile()指定要复制的文件,它的参数是文件的URI(如果是 HDFS上的文件,可以这样:hdfs://namenode:9000/home/XXX/file,其中9000是自己配置的NameNode端口 号)。JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。
(2)用户使用 DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。
DistributedCache方法:(DistributedCache 是一个提供给Map/Reduce框架的工具,用来缓存文件(text, archives, jars and so on)文件的默认访问协议为(hdfs://).
DistributedCache将拷贝缓存的文件到Slave节点在任何Job在节点上执行之前。
文件在每个Job中只会被拷贝一次,缓存的归档文件会被在Slave节点中解压缩。)
符号链接
每个存储在HDFS中的文件被放到缓存中后都可以通过一个符号链接使用。
URI hdfs://namenode/test/input/file1#myfile 你可以在程序中直接使用myfile来访问 file1这个文件。 myfile是一个符号链接文件。
12.MAP如何排序
在map端一共经历两次的排序:
当map函数产生输出时,会首先写入内存的环形缓冲区,当达到设定的阈值,在刷写磁盘之前,后台线程会将缓冲区的数据划分成相应的分区。在每个分区中,后台线程按键进行内排序,在Map任务完成之前,磁盘上存在多个已经分好区,并排好序的、大小和缓冲区一样的溢写文件,这时溢写文件将被合并成一个已分区且已排序的输出文件。由于溢写文件已经经过第一次排序,所以合并分区文件时只需要再做一次排序就可使输出文件整体有序。
13.什么是inputsplit
InputSplit是MapReduce对文件进行处理和运算的输入单位,只是一个逻辑概念,每个InputSplit并没有对文件实际的切割,只是记录了要处理的数据的位置(包括文件的path和hosts)和长度(由start和length决定)。
14.MR中使用了哪些接口?(或者是抽象类)
FileinputFormat、Mapper、Reducer、FileoutputFormat、Combiner、Partitioner等