目录
Hadoop
分布式计算平台,同时也是一个生态圈
- hadoop 1.X HDFS+MapReducer+Common
- hadoop 2.X HDFS+MAP+Reducer+Common
- hadoop 3.X java7->java8,引入纠删码,重写shell脚本,支持超过两个NameNode,默认端口改变
HDFS
分布式文件存储系统(可靠,高吞吐),利用目录树定位文件
- 可靠性-维护多个副本
- 扩展性-随时增减服务器
- 高效性-task并行
- 容错性-失败的任务重新分配执行
- 适合一次写入多次读出
- 支持数据的追加,不支持随机修改
HDFS组件
NameNode
- NameNode 存储文件的元数据,位置信息
- 配置副本策略
- 管理数据块映射信息
- 处理读写请求
DataNode
- DataNode 存储文件的真实数据,并做数据校验
- 一个数据块在DN中会存储数据本身,数据长度,检验和以及时间戳。同时DN启动后会向NN进行注册,后续每隔一小时向NN汇报数据块信息,同时每三秒进行一次NN心跳并带回NN指令,如果10分钟没有心跳信号,NN会认为该节点宕机。
- 在数据节点退役过程中推荐使用黑名单进行退役,辞职后会进行HDFS数据转移。
SecondaryNameNode
- SecondaryNameNode 对NameNode做备份,但不能顶替NN提供服务
- 定期合并镜像文件,编辑日志,推送给NN
- 可以恢复NN的数据(可能不完整)
Client
- Client切分上传的文件
- 告知NN文件的位置信息,交互DN的读写数据
- 通过命令管理HDFS
HDFS文件的上传与下载
- 上传:客户端通过HDFS对象向NameNode提交上传请求,NN确定文件状态以及父目录是否存在,返回许可。随后用户上传文件的第一个数据块,请求NN返回DataNode,NN根据请求返回三个DN节点,用户通过输出流请求在一个DN上上传数据(上传的DN根据网络拓扑计算决定),然后该DN会调用其他的DN节点将这个通信信道建立完成。三个节点逐级应答客户端,客户端向第一个DN节点上传一个数据块,以packet为单位,DN收到后先进行落盘处理,同时将该packet传送给第二个DN节点然后再传给第三个DN节点。当第一个块传输完成后,第二个数据块重复上面的动作,传递完成后关闭传输流,传输过程中,第一个DN节点会将packet放入一个应答队列,待所有节点相应完成后表示上传成功。
- 下载: 客户端访问HDFS对象,向NameNode请求下载某文件,NameNode返回文件的元数据信息,以及数据块坐在的位置。客户端得到信息后获取文件输入流,根据就近原则随机原则随机挑选一个DN节点获取packet,客户端收到后现在本地缓存,然后写入目标文件。
NameNode与SecondaryNameNode的机制
- NN在启动后会将fsimage和edits加载到内存里,格式化后则是创建。客户端对HDFS进行操作后,NN先将操作记录到日志中,然后再内存中进行操作,2NN向NN询问是否CheckPoint,带回指令。如果CheckPoint,NN会生成一个滚动的日志文件,一个磁盘中编辑日志的复制文件,将磁盘中的镜像文件和复制好的编辑日志文件复制到2NN中,加载到2NN内存中合并成一个合并文件,返回到NN中,NN用重命名的方式覆盖原文件。
- fsimage是HDFS文件系统中元数据的一个永久性检查点
- edits存放HDFS文件系统中所有的更新操作
- CheckPoint触发点为1小时或者edits执行了一百万次操作。2NN在一分钟内确认三次NN的操作次数
Yarn组件
- ResourceManager 处理客户端请求,监控NodeManager,启动ApplicationMaster,调度资源
- NodeManager 管理单个节点上的资源,处理ResourceManager的命令,处理ApplicationMaster的命令
- Contianer 封装单个节点上的资源
- ApplicationMaster 负责数据切分,为应用申请资源,监控任务
MapReduce框架⭐
- 常用的数据序列化类型 String-》Text | Map-》MapWritable | Array-》ArrayWritable
- 一个运算程序一般是一个map阶段和一个reduce阶段,MapTask并发执行,互不相干。ReduceTask并发执行,依赖MapTask的数据结果。
- 关于进程,mrAppMaster负责过程调度和状态协调,MapTask负责map阶段的数据处理。ReduceTask负责reduce阶段的数据处理。
MapReduce
Mapper与Reducer的继承
- 继承自Mapper并重写map方法,读取文件中内容并格式化输出到Reduce中处理。
- 继承自Reducer并重写reduce方法,将map输出的KV对接收处理后提交到job中执行。
Writable序列化接口
- Writable序列化接口是一个javaBean对象,其中封装了需要系列化的参数。其中重写的序列化与反序列化方法中的值顺序必须一致。提供空参构造函数来实现反射调用。另外还需要重写toString方法,令输出数据可观。
MapTask的工作机制(分而治之思想)
- 通过TextInputFormat组件(可自定义)将文件进行逻辑切片(HDFS是物理切块),后续有多少个切片就会启动多少个MapTask。其中每个切片大小与blok大小对应为128M。
- 文件切分完成后交给LineRecordReader按照换行符依次读取数据交给定义的map方法。
- map方法输出的KV对会进入一个环形缓冲区(内存区域),按照Key的HashCode值%NumReduceTask数量进行分区,环形缓冲区的默认大小是100M,达到80M后会进行溢写,同时会进行分区内按照key执行快速排序,在最后一次溢写结束后,会进行分区内的归并排序,最后输出一个文件给MapTask,文件中会有多个分区的索引来记录偏移量。
MapTask的并行度
- 移动计算比移动数据划算、即写满blok大小防止出现数据的移动(数据本地化-HDFS的短路读取)
- 单个数据切片大小为blok大小128M,最大超限10%,即129M也会分为一个切片。MapTask的并行度取决于split的数量。
ReduceTask的工作机制
- Copy阶段,复制Map端输出的一个分区的一片数据,对于同一个分区的数据,一定会进入同一个ReduceTask。在内存缓冲区中merge合并,溢出到磁盘的数据进行归并排序合并。按照Key分组,调用一次Reduce方法。
ReduceTask的并行度
- ReduceTask的并行度通过job.setNumReduceTasks() 设置。0是与MapTask保持一致,不设置默认为一个。如果数据分配不均会产生数据倾斜的问题,即某个ReduceTask处理的数据量远远大于其他处理的数据量
Shuffle机制⭐
- Map阶段处理后的数据传给Reduce阶段被称为Shuffle,是MapReduce框架中最关键的一个流程。
- 数据分区,排序,分组,预聚合(combine),合并
- combiner使用的前提是不影响最终业务的逻辑。combiner是map方法后的执行流程,所以输入输出要和map保持一致
MR中的排序
- 部分排序:Hadoop的默认行为,MapReduce根据key排序,保证输出文件内部有序。
- 全排序:丧失了MapReduce的并行功能,由一台机器处理全部文件,处理大型文件时效率极低,通过设置一个ReduceTask实现。
- 辅助排序:在Reduce端对接受的Key进行分组。
- 二次排序:自定义排序过程。
MR中文件的输入和输出
输入
- TextInputFormat (普通文本文件,MR框架默认的读取实现类型)
- KeyValueTextInputFormat(读取一行文本数据按照指定分隔符,把数据封装为kv类型)
- NLineInputF ormat(读取数据按照行数进行划分分片)
- CombineTextInputFormat(合并小文件,避免启动过多MapTask任务)
- CombineTextInputFormat切片原理
切片生成过程分为两部分:虚拟存储过程和切片过程
虚拟存储过程:把输入目录下所有文件大小,依次和设置的setMaxInputSplitSize值进行比 较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于 两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时 将文件均分成2个虚拟存储块(防止出现太小切片)
切片过程:判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个 切片。如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
例如四个小文件:1.txt -->2M ;2.txt-->7M;3.txt-->0.3M;4.txt--->8.2M,// 如果不设置InputFormat,它默认用的是TextInputFormat.class job.setInputFormatClass(CombineTextInputFormat.class);
//虚拟存储切片最大值设置4m CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);
输出
- 默认的输出格式是TextOutputFormat,它把每条记录写为文本行。它的键和值可以是任意类型,
因为TextOutputFormat调用toString()方法把它们转换为字符串。- 将SequenceFileOutputFormat输出作为后续MapReduce任务的输入,这是一种好的输出格式,因为它的格式紧凑,很容易被压缩。