Hadoop
1. Hadoop运行模式
- 本地模式(单机模式)
- 伪分布式模式:一台机器模拟分布式环境
- 完全分布式模式:分布式环境
2. Hadoop生态圈组件
- Zookeeper:是一个开源的分布式应用程序协调服务,基于zookeeper可以实现同步服务,配置维护,命名服务
- Hive:基于Hadoop的一个数据仓库工具,可以将结构化的数据档映射为一张数据库表,并提供简单的sql 查询功能,可以将sql语句转换为MapReduce任务进行运行
- Flume:一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统
- Hbase:是一个分布式的、面向列的开源数据库, 利用Hadoop HDFS作为其存储系统
- Sqoop:将一个关系型数据库中的数据导进到Hadoop的 HDFS中,也可以将HDFS的数据导进到关系型数据库中
3. Hadoop集群中Hadoop都分别需要启动哪些进程,它们的作用分别是什么
- NameNode:它是hadoop中的主服务器,管理文件系统名称空间和对集群中存储的文件的访问,保存有metadate
- SecondaryNameNode:它不是namenode的冗余守护进程,而是提供周期检查点和清理任务。帮助NN合并editslog,减少NN启动时间
- DataNode:它负责管理连接到节点的存储(一个集群中可以有多个节点)。每个存储数据的节点运行一个datanode守护进程
- ResourceManager(JobTracker):JobTracker负责调度DataNode上的工作。每个DataNode有一个TaskTracker,它们执行实际工作
- NodeManager:(TaskTracker)执行任务
- DFSZKFailoverController:高可用时它负责监控NN的状态,并及时的把状态信息写入ZK。它通过一个独立线程周期性的调用NN上的一个特定接口来获取NN的健康状态。FC也有选择谁作为Active NN的权利,因为最多只有两个节点,目前选择策略还比较简单(先到先得,轮换)
- JournalNode:高可用情况下存放namenode的editlog文件
4. Hadoop序列化和反序列化及自定义bean对象实现序列化
序列化和反序列化
- 序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输
- 反序列化就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据,转换成内存中的对象
- Java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系等),不便于在网络中高效传输。所以,hadoop自己开发了一套序列化机制(Writable),精简、高效
自定义bean对象要想序列化传输步骤及注意事项
- 必须实现Writable接口
- 反序列化时,需要反射调用空参构造函数,所以必须有空参构造
- 重写序列化方法
- 重写反序列化方法
- 注意反序列化的顺序和序列化的顺序完全一致
- 要想把结果显示在文件中,需要重写toString(),且用"\t"分开,方便后续用
- 如果需要将自定义的bean放在key中传输,则还需要实现comparable接口,因为mapreduce框中的shuffle过程一定会对key进行排序
5. FileInputFormat切片机制
- job提交流程源码详解
waitForCompletion() submit(); // 1、建立连接 connect(); // 1)创建提交job的代理 new Cluster(getConfiguration()); // (1)判断是本地yarn还是远程 initialize(jobTrackAddr, conf); // 2、提交job submitter.submitJobInternal(Job.this, cluster) // 1)创建给集群提交数据的Stag路径 Path jobStagingArea = JobSubmissionFiles.getStagingDir(cluster, conf); // 2)获取jobid ,并创建job路径 JobID jobId = submitClient.getNewJobID(); // 3)拷贝jar包到集群 copyAndConfigureFiles(job, submitJobDir); rUploader.uploadFiles(job, jobSubmitDir); // 4)计算切片,生成切片规划文件 writeSplits(job, submitJobDir); maps = writeNewSplits(job, jobSubmitDir); input.getSplits(job); // 5)向Stag路径写xml配置文件 writeConf(conf, submitJobFile); conf.writeXml(out); // 6)提交job,返回提交状态 status = submitClient.submitJob(jobId, submitJobDir.toString(), job.getCredentials());
6. 在一个运行的Hadoop 任务中,什么是InputSplit
FileInputFormat源码解析(input.getSplits(job))
找到你数据存储的目录
开始遍历处理(规划切片)目录下的每一个文件
遍历第一个文件ss.txt
获取文件大小fs.sizeOf(ss.txt)
计算切片大小
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
默认情况下,切片大小=blocksize
开始切,形成第1个切片:ss.txt—0:128M 第2个切片ss.txt—128:256M 第3个切片ss.txt—256M:300M(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分一块切片)
将切片信息写到一个切片规划文件中
整个切片的核心过程在getSplit()方法中完成
数据切片只是在逻辑上对输入数据进行分片,并不会再磁盘上将其切分成分片进行存储。InputSplit只记录了分片的元数据信息,比如起始位置、长度以及所在的节点列表等。
注意:block是HDFS上物理上存储的存储的数据,切片是对数据逻辑上的划分。
提交切片规划文件到yarn上,yarn上的MrAppMaster就可以根据切片规划文件计算开启maptask个数。
7. 如何判定一个job的map和reduce的数量
map数量
- splitSize=max{minSize,min{maxSize,blockSize}}
- map数量由处理的数据分成的block数量决定default_num = total_size / split_size;
reduce数量
- reduce的数量job.setNumReduceTasks(x);x 为reduce的数量。不设置的话默认为 1。
8. Maptask的个数由什么决定
一个job的map阶段MapTask并行度(个数),由客户端提交job时的切片个数决定
9. MapTask和ReduceTask工作机制
MapTask工作机制
- Read阶段:Map Task通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value
- Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value
- Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中
- Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作
- Combine阶段:当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件
ReduceTask工作机制
- Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中
- Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中
- Sort阶段:按照MapReduce语义,用户编写reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可
- Reduce阶段:reduce()函数将计算结果写到HDFS上