Hadoop

304 阅读7分钟

HDFS

Hadoop Distributed File Sysytem,分布式文件系统,适合一写多读。

组成架构

NameNode

Master,管理者

  1. 管理HDFS的名称空间
  2. 配置副本策略
  3. 管理数据块(Block)映射信息
  4. 处理客户端读写请求
DataNode

NameNode下达命令,DataNode负责执行

  1. 存储实际的数据块
  2. 执行数据块的读/写操作
Client

读/写请求客户端

  1. 文件切分。文件上传HDFS时,Client将文件切分成一个个Block(Hadoop 1.x 64M,Hadoop 2.x 128M),然后进行上传
  2. 与NameNode交互,获取文件的位置信息
  3. 与DataNode交互,读/写数据
  4. Client提供命令管理HDFS,比如NameNode格式化
  5. Client通过命令访问HDFS,比如对HDFS增删改查操作
Secondary NameNode

不是NameNode的热备,当NameNode挂掉的时候,不能马上替换NameNode提供服务

  1. 辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode;
  2. 紧急情况下,可辅助恢复NameNode

HDFS写流程

  1. 客户端通过Distribute FileSystem模块向NameNode请求上传文件,NameNode检查目标文件是否已经存在,父目录是否已经存在
  2. NameNode返回是否可以上传
  3. 客户端请求第一个Block上传到哪几个DataNode服务器上
  4. NameNode返回3个DataNode节点,分别为dn1、dn2、dn3
  5. 客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,dn2调用dn3,通信管道完成建立
  6. dn1、dn2、dn3逐级应答客户端
  7. 客户端向dn1上传第一个Block,以Packet为单位,dn1收到一个Packet会传给dn2、dn3;dn1每传一个Packet会放入一个应答队列等待应答
  8. 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器(重复3-7步)。

HDFS读流程

  1. 客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件所在的DataNode地址
  2. 挑选一台DataNode(就近随机原则)服务器,请求读取数据
  3. DataNode开始上传数据给客户端(从磁盘里面读取数据输入流,以Packet为单位做校验)
  4. 客户端以Packet为单位接收,先在本地缓存,然后写入目标文件

NameNode & SecondaryNameNode

NameNode启动
  1. 第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存
  2. 客户端对元数据进行增删改请求
  3. NameNode记录操作日志,更新滚动日志
  4. NameNode在内存中对数据进行增删改
Secondary NameNode工作
  1. Secondary NameNode询问NameNode是否需要CheckPoint,直接带回NameNode是否检查结果
  2. Secondary NameNode请求执行CheckPoint
  3. NameNode滚动正在写的Edits日志
  4. 将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode
  5. Secondary NameNode加载编辑日志和镜像文件到内存,并合并
  6. 生成镜像文件fsimage.chkpoint
  7. 拷贝fsimage.chkpoint到NameNode
  8. NameNode将fsimage.chkpoint重命名成fsimage

HDFS小文件处理

大量小文件元数据信息存在NameNode中,占用资源,影响查询效率

  1. 采用har归档方式,将小文件归档
  2. 采用CombineTextInputFormat
  3. 有小文件场景开启JVM重用;如果没有小文件,不要开启JVM重用,因为会一直占用使用到的task卡槽,直到任务完成才释放

MapReduce

Map:负责把一个任务分解成多个任务 Reduce:负责分解后多任务处理结果的汇总

MapeReduce工作流程

Shuffle机制

优化

Map阶段
  1. 增大环形缓冲区大小,由100m扩大到200m
  2. 增大环形缓冲区溢写比例,由80%扩大到90%
  3. 减小对溢写文件的merge次数(10个文件,一次20merge)
  4. 不影响实际业务的前提下,采用Combiner提前合并,减小I/O
Reduce阶段
  1. 合理设置Map和Reduce数:太少会导致Task等待,延长处理时间;太多会导致Map、Reduce任务间资源竞争,造成处理超时等错误
  2. 设置Map、Reduce共存:调整slowstart.completedmaps参数,使Map运行到一定程度后,Reduce也开始运行,减小Reduce等待时间
  3. 规避使用Reduce,因为Reduce用于连续数据集是将产生大量的网络消耗
  4. 增加每个Reduce去Map中拿数据的并行度
  5. 集群性能下,增大Reduce端存储数据内存大小
IO传输

采用数据压缩,减少网络IO。

  1. map输入端考虑数据量大小和切片,LZO要想支持切片必须创建索引
  2. map输出端考虑速度,snappy、LZO速度快
  3. reduce输出端看需求,如果作为下一个mr输入需要考虑切片,永久保存考虑压缩率大的gzip
其他
  1. NodeManager默认内存8G,根据服务器灵活调整。如128G内存,配置100G左。yarn.nodemanager.resource.memory-mb
  2. 单任务默认内存8G,根据任务数据量灵活调整,如128M数据,配置1G内存。yarn.scheduler.maximum-allocation-mb
  3. mapreduce.map.memory.mb:控制分配给MapTask内存上限,超过会kill掉进程。默认内存1G,当数据量大于128M是。可以增加MapTask内存,最大到4-5G
  4. mapreduce.reduce.memory.mb:控制ReduceTask内存上限,默认内存大小1G,如果数据量大于128M,可增加ReduceTask内存大小4-5G
  5. mapreduce.map.java.opts:控制MapTask对内存大小
  6. mapreduce.reduce.java.opts:控制ReduceTask堆内存大小
  7. 增加MapTask、ReduceTask的CPU核数
  8. 增加Container的CPU核数
  9. 在hdfs-site.xml中配置多目录
  10. NameNode由一个工作线程池,用来处理不同DataNode的并发心跳以及客户端并发元数据操作。dfs.namenode.handler.count = 20 * log2(Cluster Size),比如集群规模为10台,此参数设置为60

Yarn

作业提交

  1. Client调用job.waitForCompletion方法,向集群提交MapReduce作业
  2. Client向RM申请一个作业id
  3. RM给CLient返回该job资源的提交路径和作业id
  4. Client提交jar包、切片信息和配置文件到指定的资源路径下
  5. Client提交完资源后,向RM申请运行MrAppMaster

作业初始化

  1. 当RM收到Client请求后,将该job添加到容量调度器中
  2. 某一个空闲的NM领取到Job
  3. 该NM创建Container,并产生MRAppMaster
  4. 下载Client提交的资源到本地

任务分配

  1. MrAppMaster向RM申请运行多个MapTask任务资源
  2. RM将运行MapTask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器

任务运行

  1. MR向两个接收任务的NodeManager发送程序启动脚本,分别启动MapTask,MapTask对数据分区排序
  2. MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask
  3. ReduceTask向MapTask获取相应分区的数据
  4. 程序运行完毕后,MR向RM申请注销

进度和状态更新

YARN中的任务将其进度和状态返回给应用管理器,客户端每秒(通过mapreduce.client.progressmonitor.pollinterval设置)向应用管理器请求进度更新,展示给用户

作业完成

除了向应用管理器请求作业进度外,客户端每5秒都会通过调用waitForCompletion()来检查作业是否完成。

资源调度器

  • FIFO:单队列,先进先出,生产环境不用
  • Capacity Scheduler 容量调度器:多队列,保证先进入的任务优先执行
  • Fair Sceduler 公平调度器:多队列,保证任务公平享有队列资源

Hadoop宕机

  1. 如果MR造成系统宕机,要控制Yarn同时运行的任务数,和每个任务申请的最大内存。调整参数yarn.scheduler.maximum-allocation-mb(单个任务可申请的最多物理内存量,默认8192M)
  2. 如果写入文件过快造成NameNode宕机,则调高Kafka的存储大小,控制从Kafka到HDFS的写入速度。

Hadoop数据倾斜

  1. 提前在map端combine,减少传输的数据量
  2. 导致数据倾斜的key分布在不同的mapper
    • 局部聚合 + 全局聚合,第一次MapReduce对导致了数据倾斜的key加上1到n的随机数,使原本相同的key分到多个Reducer中进行局部聚合;第二次MapReduce取消key的随机前缀,进行全局聚合
    • 增加Reducer,提升并行度,JobConf.setNumReduceTasks(int)
    • 实现自定义分区,根据数据分布情况,自定义散列函数,将key均匀分配到不同的Reducer