一. Hadoop 基础:
1. 大数据特点(4V)
- Volume: 大量
- Velocity: 高速
- Variety: 多样
- Value: 低价值密度
2. Hadoop的优势(4高):
- 高可靠性: Hadoop底层维护多个数据副本
- 高扩展性: 在集群间分配任务数据, 可方便扩展数以千计的节点.
- 高效性: 在MapReduce的思想下, Hadoop是并行工作的
- 高容错性: 能够自动将失败的任务重新分配
3. Hadoop组成(面试重点):
- Hadoop1.x:
- HDFS(数据存储)
- MapReduce(计算+资源调度)
- Common(辅助工具)
- Hadoop2.x:
- HDFS(数据存储)
- MapReduce(计算)
- Yarn(资源调度)
- Common(辅助工具)
- 总结:
- 在Hadoop1.x时代, Hadoop中的MapReduce同时处理业务逻辑运算和资源的调度, 耦合性角度;
- 在Hadoop2.x时代, 增加了yarn. Yarn只负责资源的调度, MapReduce只负责运算.
4. HDFS架构概述:
- NameNode(NN):
存储文件的元数据, 如文件名, 文件目录结构, 文件属性(生成时间, 副本数, 文件权限), 以及每个文件的块列表和块所在的DataNode等. - DataNode(DN):
在本地文件系统存储文件块数据, 以及块数据的校验和. - Secondary NameNode(2NN)
用来监控HDFS状态的辅助后台程序, 每隔一段时间获取HDFS元数据的快照.
5. Yarn架构概述:
-
ResourceManager(RM):
- 处理客户端请求
- 监控NodeManager
- 启动或监控ApplicationMaster
- 资源的分配与调度
-
ApplicationMaster(AM):
- 负责数据调度切分
- 为数据查询申请资源并分配内部的任务
- 任务的监控容错
-
NodeManager(NM):
- 管理单个节点上的资源
- 处理来自ResourceManager的命令
- 处理来自ApplicationMaster的命令
-
Container:
Container是yarn中的资源抽象, 它封装了某个节点上的多维资源, 如内存, CPU, 磁盘, 网络等.
6. MapReduce架构概述:
- Map阶段并行处理输入数据
- Reduce阶段对Map结果进行汇总
二. HDFS
1. 定义:
HDFS(Hadoop Distributed File System), 它是一个分布式的文件系统. HDFS适用于一次写入, 多次读出的场景, 且不支持文件的修改.
2. 优缺点:
1. 优点
- 高容错性:
- 数据自动保存多个副本, 可以通过增加副本的形式, 提高容错性.
- 某个副本丢失以后, 它可以自动恢复.
- 适合批处理
- 移动计算而非数据
- 数据位置暴露给计算框架(Block偏移量)
- 适合处理大数据
- 数据规模: 文件规模可以达到GB, TB, 甚至PB级别
- 文件规模: 能够处理百万规模以上的文件数量/
- 可构架在廉价机器上
2. 缺点:
- 不适合低延时数据访问
- 无法高效的对大量小文件进行存储
- 存储大量小文件的时候, 它会占用NameNode大量的内存来存储文件目录和块信息.
- 小文件存储的寻址时间会超过读取时间, 它违反了HDFS的设计目标.
- 不支持并发写入和文件随机修改
- 一个文件只能有一个写, 不允许多线程同时写
- 仅支持数据追加, 不支持文件的随机修改
3. HDFS组成架构
1. NameNode(NN):
-
职责:
- 负责客户端请求(读写数据 请求 )的响应
- 维护目录树结构( 元数据的管理: 查询,修改 )
- 配置和应用副本存放策略
- 管理集群数据块负载均衡问题
-
元数据存储机制
- 内存中有一份完整的元数据(内存 metadata)
- 磁盘有一个“准完整”的元数据镜像(fsimage)文件(在 namenode 的工作目录中)
- 用于衔接内存 metadata 和持久化元数据镜像 fsimage 之间的操作日志(edits 文件)
- 当客户端对 hdfs 中的文件进行新增或者修改操作,操作记录首先被记入 edits 日志 文件中,当客户端操作成功后,相应的元数据会更新到内存 metadata 中
-
保存matadata信息包括:
- 文件owership和permissions
- 文件大小, 时间
- (block列表: block偏移量), 位置信息
- Block每个副本位置(由DataNode上报)
-
持久化:
- NameNode的matadata信息在启动后会加载到内存
- metadata存储到磁盘文件名为"fsimage"(时点备份)
- Block的位置信息不回保存到fsimage
- edits记录对matadata的操作日志
-
NameNode内存中存储的是: fsimage + edits
- fsimage: 元数据镜像文件(文件系统的目录树)
- edits: 元数据的操作目录(针对文件系统做的修改操作记录)
2. DataNode(DN):
- 就是Slave. NameNode下达命令, DataNode执行实际的操作.
- 存储实际的数据库
- 执行数据库的读, 写操作
- 细节
- 本地磁盘目录存储数据(Block), 文件形式
- 同时存储Block的元数据信息文件
- 启动DN是会向NN汇报block信息
- 通过向NN发送心跳保持与其联系(3秒一次), 如果NN 10分钟没有收到DN的心跳, 则认为其已经lost, 并copy其上的block到其它的DN
3. Client:
- 文件切分: 文件上传HDFS的时候, Client将文件切分成一个个的Block, 然后进行上传
- 与NameNode交互, 获取文件的位置信息
- 与DataNode交互, 读取或写入数据
- Client提供一些命令来管理HDFS, 比如NameNode格式化.
- Client可以通过一些命令来访问HDFS, 比如对HDFS增删改查操作
4. Secondary NameNode(2NN):
-
并非NameNode的热备份. 当NameNode挂掉的时候, 它并不能马上替换NameNode并提供服务
- 辅助NameNode, 分担其工作量, 比如定期合并Fsimage和Edits, 并推送给NameNode
- 在紧急情况下, 可辅助恢复NameNode
-
SNN执行合并的时机(什么时候checkpoint):
- 根据配置文件设置的时间间隔fs.checkpoint.period, 默认3600秒
- 根据配置文件设置edits.log大小 fs.checkpoint.size规定edits文件的最大值, 默认是64MB
-
工作流程
- secondary通知namenode切换edits文件
- secondary从namenode获得fsimage和edits(通过http);
- secondary将fsimage载入内存,然后开始合并edits;
- secondary将新的fsimage发回给namenode;
- namenode用新的fsimage替换旧的fsimage;
-
扩展:什么是热备份和冷备份?
- 热备份:b是a的热备份,如果a坏掉。那么b马上运行代替a的工作。
- 冷备份:b是a的冷备份,如果a坏掉。那么b不能马上代替a工作。但是b上存储a的一些信息,减少a坏掉之后的损失。
5. HDFS中的block, paket, chunk
- block
文件上传前需要分块,这个块就是block,一般为128MB. 块太小:寻址时间占比过高。块太大:Map任务数太少,作业执行速度变慢。它是HDFS中最大的一个单位。 - packet
packet是第二大的单位,它是client端向DataNode,或DataNode的PipLine之间传数据的基本单位,默认64KB。 - chunk
chunk是最小的单位,它是client向DataNode,或DataNode的PipLine之间进行数据校验的基本单位,默认512Byte,因为用作校验,故每个chunk需要带有4Byte的校验位。所以实际每个chunk写入packet的大小为516Byte。由此可见真实数据与校验值数据的比值约为128 : 1。(即64*1024 / 512)
6. HDFS的写流程
- 使用 HDFS 提供的客户端 Client,向远程的 namenode 发起 RPC 请求
- namenode 会检查要创建的文件是否已经存在,创建者是否有权限进行操作,成功则会 为文件创建一个记录,否则会让客户端抛出异常
- 当客户端开始写入文件的时候,客户端会将文件切分成多个 packets,并在内部以数据队列“data queue(数据队列)”的形式管理这些 packets,并向 namenode 申请 blocks,获 取用来存储 replicas 的合适的 datanode 列表,列表的大小根据 namenode 中 replication 的设定而定
- 开始以 pipeline(管道)的形式将 packet 写入所有的 replicas 中。客户端把 packet 以流的 方式写入第一个 datanode,该 datanode 把该 packet 存储之后,再将其传递给在此 pipeline 中的下一个 datanode,直到最后一个 datanode,这种写数据的方式呈流水线的形式
- 最后一个 datanode 成功存储之后会返回一个 ack packet(确认队列),在 pipeline 里传递 至客户端,在客户端的开发库内部维护着"ack queue",成功收到 datanode 返回的 ack packet 后会从"data queue"移除相应的 packet
- 如果传输过程中,有某个 datanode 出现了故障,那么当前的 pipeline 会被关闭,出现故 障的 datanode 会从当前的 pipeline 中移除,剩余的 block 会继续剩下的 datanode 中继续 以 pipeline 的形式传输,同时 namenode 会分配一个新的 datanode,保持 replicas 设定的 数量
- 客户端完成数据的写入后,会对数据流调用 close()方法,关闭数据流
- 只要写入了 dfs.replication.min(最小写入成功的副本数)的复本数(默认为 1),写操作 就会成功,并且这个块可以在集群中异步复制,直到达到其目标复本数(dfs.replication 的默认值为 3),因为 namenode 已经知道文件由哪些块组成,所以它在返回成功前只需 要等待数据块进行最小量的复制
7. HDFS的读流程
- 客户端调用FileSystem 实例的open 方法,获得这个文件对应的输入流InputStream
- 通过RPC 远程调用NameNode ,获得NameNode 中此文件对应的数据块保存位置,包括这个文件的副本的保存位置( 主要是各DataNode的地址)
- 获得输入流之后,客户端调用read 方法读取数据。选择最近的DataNode 建立连接并读取数据
- 如果客户端和其中一个DataNode 位于同一机器(比如MapReduce 过程中的mapper 和reducer),那么就会直接从本地读取数据
- 到达数据块末端,关闭与这个DataNode 的连接,然后重新查找下一个数据块
- 不断执行第2 - 5 步直到数据全部读完
- 客户端调用close ,关闭输入流DF S InputStream
8.HDFS保证可靠性的措施
- 冗余备份
每个文件存储成一系列数据块(Block)。为了容错,文件的所有数据块都会有副本(副本数量即复制因子,课配置)(dfs.replication) - 副本存放
采用机架感知(Rak-aware)的策略来改进数据的可靠性、高可用和网络带宽的利用率 - 心跳检测
NameNode周期性地从集群中的每一个DataNode接受心跳包和块报告,收到心跳包说明该DataNode工作正常 - 安全模式
系统启动时,NameNode会进入一个安全模式。此时不会出现数据块的写操作 - 数据完整性检测
HDFS客户端软件实现了对HDFS文件内容的校验和(Checksum)检查(dfs.bytes-per-checksum)
9. 心跳机制
- Hadoop 是 Master/Slave 结构,Master 中有 NameNode 和 ResourceManager,Slave 中有 Datanode 和 NodeManager
- Master 启动的时候会启动一个 IPC(Inter-Process Comunication,进程间通信)server 服 务,等待 slave 的链接
- Slave 启动时,会主动链接 master 的 ipc server 服务,并且每隔 3 秒链接一次 master,这 个间隔时间是可以调整的,参数为 dfs.heartbeat.interval,这个每隔一段时间去连接一次 的机制,我们形象的称为心跳。Slave 通过心跳汇报自己的信息给 master,master 也通 过心跳给 slave 下达命令
- NameNode 通过心跳得知 Datanode 的状态 ,ResourceManager 通过心跳得知 NodeManager 的状态
- 如果 master 长时间都没有收到 slave 的心跳,就认为该 slave 挂掉了。
10. HDFS2.x与HDFS1.x的区别
- 解决了HDFS1.x中单点故障
- HDFS HA: 通过主备NameNode解决
- 如果主NameNode发生故障, 则切换到备NameNode上
- 解决内存受限问题
- HDFS FEderation(联邦)
- 水平扩展, 支持多个NameNode
- 每个NameNode分管一部分目录
- 所有NameNode共享所有DataNode存储资源
- 2.x仅是架构上发生了变化, 使用方式不变
11. HDFS 2.0 HA
-
主备NameNode
-
解决单点故障(属性, 位置)
- 主NameNode对外提供服务,备NameNode同步主NameNode元数据,以待切换
- 所有DataNode同时向两个NameNode汇报数据块信息(位置)
- JNN:集群(属性)
- standby:备,完成了edits.log文件的合并产生新的image,推送回ANN
-
两种切换选择
- 手动切换:通过命令实现主备之间的切换,可以用HDFS升级等场合
- 自动切换:基于Zookeeper实现
-
基于Zookeeper自动切换方案
- ZooKeeper Failover Controller:监控NameNode健康状态
- 并向Zookeeper注册NameNode
- NameNode挂掉后,ZKFC为NameNode竞争锁,获得ZKFC 锁的NameNode变为active
三. MapReduce
1. MapReduce简介
- 什么是MapReduce?
- Mapreduce 是一个分布式运算程序的编程框架,是用户开发"基于 hadoop 的数据分析 应用"的核心框架
- Mapreduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的 分布式运算程序,并发运行在一个hadoop 集群上
- 为什么需要 MapReduce?
- 海量数据在单机上处理因为硬件资源限制,无法胜任
- 将单机版程序扩展到集群来分布式运行,将极大增加程序的复杂度和开发难度
- 引入MapReduce 框架后,开发人员可以将绝大部分工作集中在业务逻辑的开发上,而将 分布式计算中的复杂性交由框架来处理
- MapReduce的优点
- 易于编程
- 良好的扩展性
- 高容错性
- 适合PB级别以上的大数据的分布式离线批处理
- MapReduce的缺点
- 难以实时计算(MapReduce处理的是存储在本地磁盘上的离线数据)
- 不能流式计算(MapReduce设计处理的数据源是静态的)
- 难以DAG计算MapReduce这些并行计算大都是基于非循环的数据流模型,也就是说,一次计算过程中,不同计算节点之间保持高度并行,这样的数据流模型使得那些需要反复使用一个特定数据集的迭代算法无法高效地运行
2. Map做什么
核心思想:分而治之
- Mapper负责“分”,即把复杂的任务分解为若干个“简单的任务”来处理。“简单的任务”包含三层含义:
- 数据或计算的规模相对原任务要大大缩小
- 就近计算原则,即任务会分配到存放着所需数据的节点上进行计算
- 这些小任务可以并行计算,彼此间几乎没有依赖关系
- Reducer负责对map阶段的结果进行汇总。至于需要多少个Reducer,用户可以根据具体问题,通过在mapred-site.xml配置文件里设置参数mapred.reduce.tasks的值,缺省值为1
3. MapReduce的工作流程
4. MapReduce程序编写规范
- 用户编写的程序分成三个部分:Mapper, Reducer, Driver(提交运行 MR 程序的客户端)
- Mapper 的输入数据是 KV 对的形式(KV 的类型可自定义)
- Mapper 的输出数据是 KV 对的形式(KV 的类型可自定义)
- Mapper 中的业务逻辑写在 map()方法中
- map()方法(maptask 进程)对每一个<k,v>调用一次
- Reducer 的输入数据类型对应 Mapper 的输出数据类型,也是 KV 对的形式
- Reducer 的业务逻辑写在 reduce()方法中
- Reducetask 进程对每一组相同 k 的<k,v>组调用一次 reduce()方法
- 用户自定义的 Mapper 和 Reducer 都要继承各自的父类
- 整个程序需要一个 Drvier 来进行提交,提交的是一个描述了各种必要信息的 job 对象
5. MapReduce程序的运行
- 一个 mr 程序启动的时候,最先启动的是 MRAppMaster,MRAppMaster 启动后根据本次 job 的描述信息,计算出需要的 maptask 实例数量,然后向集群申请机器启动相应数量的 maptask 进程
- maptask 进程启动之后,根据给定的数据切片(哪个文件的哪个偏移量范围)范围进行数 据处理,主体流程为:
- 利用客户指定的 InputFormat 来获取 RecordReader 读取数据,形成输入 KV 对
- 将输入 KV 对传递给客户定义的 map()方法,做逻辑运算,并将 map()方法输出的 KV 对收 集到缓存
- 将缓存中的 KV 对按照 K 分区排序后不断溢写到磁盘文件
- MRAppMaster 监控到所有 maptask 进程任务完成之后(真实情况是,某些 maptask 进 程处理完成后,就会开始启动 reducetask 去已完成的 maptask 处 fetch 数据),会根据客户指 定的参数启动相应数量的 reducetask 进程,并告知 reducetask 进程要处理的数据范围(数据 分区)
- educetask 进程启动之后,根据 MRAppMaster 告知的待处理数据所在位置,从若干台 maptask 运行所在机器上获取到若干个 maptask 输出结果文件,并在本地进行重新归并排序, 然后按照相同 key 的 KV 为一个组,调用客户定义的 reduce()方法进行逻辑运算,并收集运 算输出的结果 KV,然后调用客户指定的 OutputFormat 将结果数据输出到外部存储