Hadoop 组成
1)Hadoop HDFS:一个高可靠、高吞吐量的分布式文件系统。
2)Hadoop MapReduce:一个分布式的离线并行计算框架。
3)Hadoop YARN:作业调度与集群资源管理的框架。
4)Hadoop Common:支持其他模块的工具模块(Configuration、RPC、序列化机制、日志 操作)。
MapReduce 定义
Mapreduce 是一个分布式运算程序的编程框架,是用户开发“基于 hadoop 的数据分析 应用”的核心框架。
Mapreduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的 分布式运算程序,并发运行在一个 hadoop 集群上。
MapReduce 架构概述
MapReduce 将计算过程分为两个阶段:Map 和 Reduce
1)Map 阶段并行处理输入数据
2)Reduce 阶段对 Map 结果进行汇总
MapReduce 优缺点
1.2.1 优点
1)MapReduce 易于编程。它简单的实现一些接口,就可以完成一个分布式程序,这个 分布式程序可以分布到大量廉价的 PC 机器上运行。也就是说你写一个分布式程序,跟写一 个简单的串行程序是一模一样的。就是因为这个特点使得 MapReduce 编程变得非常流行。
2)良好的扩展性。当你的计算资源不能得到满足的时候,你可以通过简单的增加机器 来扩展它的计算能力。
3)高容错性。MapReduce 设计的初衷就是使程序能够部署在廉价的 PC 机器上,这就 要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一 个节点上运行,不至于这个任务运行失败,而且这个过程不需要人工参与,而完全是由 Hadoop 内部完成的。
4)适合 PB 级以上海量数据的离线处理。这里加红字体离线处理,说明它适合离线处 理而不适合在线处理。比如像毫秒级别的返回一个结果,MapReduce 很难做到。
1.2.2 缺点
MapReduce 不擅长做实时计算、流式计算、DAG(有向图)计算。
1)实时计算。MapReduce 无法像 Mysql 一样,在毫秒或者秒级内返回结果。
2)流式计算。流式计算的输入数据是动态的,而 MapReduce 的输入数据集是静态的, 不能动态变化。这是因为 MapReduce 自身的设计特点决定了数据源必须是静态的。
3)DAG(有向图)计算。多个应用程序存在依赖关系,后一个应用程序的输入为前一 个的输出。在这种情况下,MapReduce 并不是不能做,而是使用后,每个 MapReduce 作业 的输出结果都会写入到磁盘,会造成大量的磁盘 IO,导致性能非常的低下。
MapReduce 核心思想
1)分布式的运算程序往往需要分成至少 2 个阶段。
2)第一个阶段的 maptask 并发实例,完全并行运行,互不相干。
3)第二个阶段的 reduce task 并发实例互不相干,但是他们的数据依赖于上一个阶段的所有 maptask 并发实例的输出。
4)MapReduce 编程模型只能包含一个 map 阶段和一个 reduce 阶段,如果用户的业务逻辑非 常复杂,那就只能多个 mapreduce 程序,串行运行。
1.4 MapReduce 进程
一个完整的 mapreduce 程序在分布式运行时有三类实例进程:
1)MrAppMaster:负责整个程序的过程调度及状态协调。
2)MapTask:负责 map 阶段的整个数据处理流程。
3)ReduceTask:负责 reduce 阶段的整个数据处理流程。
MapReduce 编程规范(八股文)
用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行 mr 程序的客户端)
1)Mapper 阶段
(1)用户自定义的 Mapper 要继承自己的父类
(2)Mapper 的输入数据是 KV 对的形式(KV 的类型可自定义)
(3)Mapper 中的业务逻辑写在 map()方法中
(4)Mapper 的输出数据是 KV 对的形式(KV 的类型可自定义)
(5)map()方法(maptask 进程)对每一个
2)Reducer 阶段
(1)用户自定义的 Reducer 要继承自己的父类
(2)Reducer 的输入数据类型对应 Mapper 的输出数据类型,也是 KV (3)Reducer 的业务逻辑写在 reduce()方法中
(4)Reducetask 进程对每一组相同 k 的
3)Driver 阶段
整个程序需要一个 Drvier 来进行提交,提交的是一个描述了各种必要信息的 job 对象
Hadoop 序列化 2.1 为什么要序列化?
一般来说,“活的”对象只生存在内存里,关机断电就没有了。而且“活的”对象只能 由本地的进程使用,不能被发送到网络上的另外一台计算机。 然而序列化可以存储“活的” 对象,可以将“活的”对象发送到远程计算机。
什么是序列化?
序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持 久化)和网络传输。
反序列化就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据,转换 成内存中的对象。
为什么不用 Java 的序列化?
Java 的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带 很多额外的信息(各种校验信息,header,继承体系等),不便于在网络中高效传输。所以, hadoop 自己开发了一套序列化机制(Writable),精简、高效。
为什么序列化对 Hadoop 很重要?
因为 Hadoop 在集群之间进行通讯或者 RPC 调用的时候,需要序列化,而且要求序列 化要快,且体积要小,占用带宽要小。所以必须理解 Hadoop 的序列化机制。
序列化和反序列化在分布式数据处理领域经常出现:进程通信和永久存储。然而 Hadoop 中各个节点的通信是通过远程调用(RPC)实现的,那么 RPC 序列化要求具有以下特点:
1)紧凑:紧凑的格式能让我们充分利用网络带宽,而带宽是数据中心最稀缺的资
2)快速:进程通信形成了分布式系统的骨架,所以需要尽量减少序列化和反序列化的 性能开销,这是基本的;
3)可扩展:协议为了满足新的需求变化,所以控制客户端和服务器过程中,需要直接 引进相应的协议,这些是新协议,原序列化方式能支持新的协议报文;
4)互操作:能支持不同语言写的客户端和服务端进行交互;
MapReduce 工作流程
1)maptask 收集我们的 map()方法输出的 kv 对,放到内存缓冲区中
2)从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件
3)多个溢出文件会被合并成大的溢出文件
4)在溢出过程中,及合并的过程中,都要调用 partitioner 进行分区和针对 key 进行排
序
5)reducetask 根据自己的分区号,去各个 maptask 机器上取相应的结果分区数据
6)reducetask 会取到同一个分区的来自不同 maptask 的结果文件,reducetask 会将这些 文件再进行合并(归并排序)
7)合并成大文件后,shuffle 的过程也就结束了,后面进入 reducetask 的逻辑运算过程 (从文件中取出一个一个的键值对 group,调用用户自定义的 reduce()方法)
Yarn 概述
Yarn 是一个资源调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式 的操作系统平台,而 MapReduce 等运算程序则相当于运行于操作系统之上的应用程序。
1)ResourceManager(rm):处理客户端请求、启动/监控 ApplicationMaster、监控 NodeManager、 资源分配与调度;
2)NodeManager(nm):单个节点上的资源管理、处理来自 ResourceManager 的命令、处理来 自 ApplicationMaster 的命令; 3)ApplicationMaster:数据切分、为应用程序申请资源,并分配给内部任务、任务监控与容 错。
4)Container:对任务运行环境的抽象,封装了 CPU、内存等多维资源以及环境变量、启动 命令等任务运行相关的信息。
Yarn 工作机制
(0)Mr 程序提交到客户端所在的节点。
(1)Yarnrunner 向 Resourcemanager 申请一个 Application。
(2)rm 将该应用程序的资源路径返回给 yarnrunner。 (3)该程序将运行所需资源提交到 HDFS 上。
(4)程序资源提交完毕后,申请运行 mrAppMaster。
(5)RM 将用户的请求初始化成一个 task。
(6)其中一个 NodeManager 领取到 task 任务。
(7)该 NodeManager 创建容器 Container,并产生 MRAppmaster。
(8)Container 从 HDFS 上拷贝资源到本地。
(9)MRAppmaster 向 RM 申请运行 maptask 资源。
(10)RM 将运行 maptask 任务分配给另外两个 NodeManager,另两个 NodeManager 分
别领取任务并创建容器。
(11)MR 向两个接收到任务的 NodeManager 发送程序启动脚本,这两个 NodeManager
分别启动 maptask,maptask 对数据分区排序。
(12)MrAppMaster 等待所有 maptask 运行完毕后,向 RM 申请容器,运行 reduce task。 (13)reduce task 向 maptask 获取相应分区的数据。
(14)程序运行完毕后,MR 会向 RM 申请注销自己。
作业提交过程之 YARN
(1)作业提交
第 0 步:client 调用 job.waitForCompletion 方法,向整个集群提交 MapReduce 作业。 第 1 步:client 向 RM 申请一个作业 id。
第 2 步:RM 给 client 返回该 job 资源的提交路径和作业 id。
第 3 步:client 提交 jar 包、切片信息和配置文件到指定的资源提交路径。
第 4 步:client 提交完资源后,向 RM 申请运行 MrAppMaster。
(2)作业初始化
第 5 步:当 RM 收到 client 的请求后,将该 job 添加到容量调度器中。
第 6 步:某一个空闲的 NM 领取到该 job。
第 7 步:该 NM 创建 Container,并产生 MRAppmaster。
第 8 步:下载 client 提交的资源到本地。
(3)任务分配
第 9 步:MrAppMaster 向 RM 申请运行多个 maptask 任务资源。
第 10 步:RM 将运行 maptask 任务分配给另外两个 NodeManager,另两个 NodeManager
分别领取任务并创建容器。
(4)任务运行
第 11 步:MR 向两个接收到任务的 NodeManager 发送程序启动脚本,这两个 NodeManager 分别启动 maptask,maptask 对数据分区排序。
第 12 步:MrAppMaster 等待所有 maptask 运行完毕后,向 RM 申请容器,运行 reduce task。 第 13 步:reduce task 向 maptask 获取相应分区的数据。
第 14 步:程序运行完毕后,MR 会向 RM 申请注销自己。
(5)进度和状态更新
YARN 中的任务将其进度和状态(包括 counter)返回给应用管理器, 客户端每秒(通过 mapreduce.client.progressmonitor.pollinterval 设置)向应用管理器请求进度更新, 展示给用户。
(6)作业完成
除了向应用管理器请求作业进度外, 客户端每 5 分钟都会通过调用 waitForCompletion() 来检查作业是否完成。时间间隔可以通过 mapreduce.client.completion.pollinterval 来设置。作 业完成之后, 应用管理器和 container 会清理工作状态。作业的信息会被作业历史服务器存储 以备之后用户核查
Mapreduce 程序效率的瓶颈
在于两点:
1)计算机性能
CPU、内存、磁盘健康、网络 2)I/O 操作优化
(1)数据倾斜
(2)map 和 reduce 数设置不合理
(3)map 运行时间太长,导致 reduce 等待过久 (4)小文件过多 (5)大量的不可分块的超大文件
(6)spill 次数过多 (7)merge 次数过多等。
6.2 MapReduce 优化方法
MapReduce 优化方法主要从六个方面考虑:数据输入、Map 阶段、Reduce 阶段、IO 传
输、数据倾斜问题和常用的调优参数。
6.2.1 数据输入
(1)合并小文件:在执行 mr 任务前将小文件进行合并,大量的小文件会产生大量的 map 任务,增大 map 任务装载次数,而任务的装载比较耗时,从而导致 mr 运行较慢。
(2)采用 CombineTextInputFormat 来作为输入,解决输入端大量小文件场景。
6.2.2 Map 阶段
1)减少溢写(spill)次数:通过调整 io.sort.mb 及 sort.spill.percent 参数值,增大触发 spill 的内存上限,减少 spill 次数,从而减少磁盘 IO。
2)减少合并(merge)次数:通过调整 io.sort.factor 参数,增大 merge 的文件数目,减 少 merge 的次数,从而缩短 mr 处理时间。
3)在 map 之后,不影响业务逻辑前提下,先进行 combine 处理,减少 I/O。
6.2.3 Reduce 阶段
1)合理设置 map 和 reduce 数:两个都不能设置太少,也不能设置太多。太少,会导 致 task 等待,延长处理时间;太多,会导致 map、reduce 任务间竞争资源,造成处理超时 等错误。
2)设置 map、reduce 共存:调整 slowstart.completedmaps 参数,使 map 运行到一定程 度后,reduce 也开始运行,减少 reduce 的等待时间。
3)规避使用 reduce:因为 reduce 在用于连接数据集的时候将会产生大量的网络消耗。
HDFS 小文件弊端
HDFS 上每个文件都要在 namenode 上建立一个索引,这个索引的大小约为 150byte,这 样当小文件比较多的时候,就会产生很多的索引文件,一方面会大量占用 namenode 的内存 空间,另一方面就是索引文件过大是的索引速度变慢。
解决方案 1)Hadoop Archive:
是一个高效地将小文件放入 HDFS 块中的文件存档工具,它能够将多个小文件打包成 一个 HAR 文件,这样就减少了 namenode 的内存使用。
2)Sequence file:
sequence file 由一系列的二进制 key/value 组成,如果 key 为文件名,value 为文件内容, 则可以将大批小文件合并成一个大文件。
3)CombineFileInputFormat:
CombineFileInputFormat 是一种新的 inputformat,用于将多个文件合并成一个单独的 split,另外,它会考虑数据的存储位置。
4)开启 JVM 重用
对于大量小文件 Job,可以开启 JVM 重用会减少 45%运行时间。
JVM 重用理解:一个 map 运行一个 jvm,重用的话,在一个 map 在 jvm 上运行完毕后, jvm 继续运行其他 map。
HDFS 优缺点
1.3.1 优点
1)高容错性 (1)数据自动保存多个副本。它通过增加副本的形式,提高容错性。 (2)某一个副本丢失以后,它可以自动恢复。
2)适合大数据处理
(1)数据规模:能够处理数据规模达到 GB、TB、甚至 PB 级别的数据。
(2)文件规模:能够处理百万规模以上的文件数量,数量相当之大。 3)流式数据访问
(1)一次写入,多次读取,不能修改,只能追加
(2)它能保证数据的一致性。 4)可构建在廉价机器上,通过多副本机制,提高可靠性。
1.3.2 缺点
1)不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。 2)无法高效的对大量小文件进行存储
(1)存储大量小文件的话,它会占用 NameNode 大量的内存来存储文件、目录和块信 息。这样是不可取的,因为 NameNode 的内存总是有限的。
(2)小文件存储的寻址时间会超过读取时间,它违反了 HDFS 的设计目标。 3)并发写入、文件随机修改
(1)一个文件只能有一个写,不允许多个线程同时写。 (2)仅支持数据 append(追加),不支持文件的随机修改。
HDFS 架构
这种架构主要由四个部分组成,分别为 HDFS Client、NameNode、DataNode 和 Secondary
NameNode。下面我们分别介绍这四个组成部分。 1)Client:就是客户端。
(1)文件切分。文件上传 HDFS 的时候,Client 将文件切分成一个一个的 Block,然后进 行存储。
(2)与 NameNode 交互,获取文件的位置信息。
(3)与 DataNode 交互,读取或者写入数据。
(4)Client 提供一些命令来管理 HDFS,比如启动或者关闭 HDFS。 (5)Client 可以通过一些命令来访问 HDFS。
2)NameNode:就是 master,它是一个主管、管理者。
(1)管理 HDFS 的名称空间。 (2)管理数据块(Block)映射信息 (3)配置副本策略 (4)处理客户端读写请求。
3) DataNode:就是 Slave。NameNode 下达命令,DataNode 执行实际的操作。 (1)存储实际的数据块。
(2)执行数据块的读/写操作。
4) Secondary NameNode:并非 NameNode 的热备。当 NameNode 挂掉的时候,它并不能马 上替换 NameNode 并提供服务。
(1)辅助 NameNode,分担其工作量。
(2)定期合并 Fsimage 和 Edits,并推送给 NameNode。 (3)在紧急情况下,可辅助恢复 NameNode。
NameNode&Secondary NameNode 工作机制
第一阶段:namenode 启动
(1)第一次启动 namenode 格式化后,创建 fsimage 和 edits 文件。如果不是第一次启
动,直接加载编辑日志和镜像文件到内存。 (2)客户端对元数据进行增删改的请求。 (3)namenode 记录操作日志,更新滚动日志。 (4)namenode 在内存中对数据进行增删改查。
2)第二阶段: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。
DataNode 工作机制
1)一个数据块在 datanode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本 身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
2)DataNode 启动后向 namenode 注册,通过后,周期性(1 小时)的向 namenode 上报 所有的块信息。
3)心跳是每 3 秒一次,心跳返回结果带有 namenode 给该 datanode 的命令如复制块数据 到另一台机器,或删除某个数据块。如果超过 10 分钟没有收到某个 datanode 的心跳,则认 为该节点不可用。
4)集群运行中可以安全加入和退出一些机器
什么是 Hive
Hive:由 Facebook 开源用于解决海量结构化日志的数据统计。
Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并 提供类 SQL 查询功能。
本质是:将 HQL 转化成 MapReduce 程序 1)Hive 处理的数据存储在 HDFS
2)Hive 分析数据底层的实现是 MapReduce 3)执行程序运行在 Yarn 上
Hive 的优缺点
1.2.1 优点
1)操作接口采用类 SQL 语法,提供快速开发的能力(简单、容易上手)
2)避免了去写 MapReduce,减少开发人员的学习成本。
3)Hive 的执行延迟比较高,因此 Hive 常用于数据分析,对实时性要求不高的场合; 4)Hive 优势在于处理大数据,对于处理小数据没有优势,因为 Hive 的执行延迟比较高。 5)Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
1.2.2 缺点
1)Hive 的 HQL 表达能力有限 (1)迭代式算法无法表达 (2)数据挖掘方面不擅长
2)Hive 的效率比较低
(1)Hive 自动生成的 MapReduce 作业,通常情况下不够智能化 (2)Hive 调优比较困难,粒度较粗
Hive 和数据库比较
由于 Hive 采用了类似 SQL 的查询语言 HQL(Hive Query Language),因此很容易 将 Hive 理解为数据库。其实从结构上来看,Hive 和数据库除了拥有类似的查询语言,再无 类似之处。本文将从多个方面来阐述 Hive 和数据库的差异。数据库可以用在 Online 的应用 中,但是 Hive 是为数据仓库而设计的,清楚这一点,有助于从应用角度理解 Hive 的特性。
1.4.1 查询语言
由于 SQL 被广泛的应用在数据仓库中,因此,专门针对 Hive 的特性设计了类 SQL 的
查询语言 HQL。熟悉 SQL 开发的开发者可以很方便的使用 Hive 进行开发。 1.4.2 数据存储位置
Hive 是建立在 Hadoop 之上的,所有 Hive 的数据都是存储在 HDFS 中的。而数据库则 可以将数据保存在块设备或者本地文件系统中。
1.4.3 数据更新
由于 Hive 是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive 中不支持对数据的改写和添加,所有的数据都是在加载的时候确定好的。而数据库中的数据 通常是需要经常进行修改的,因此可以使用 INSERT INTO ... VALUES 添加数据,使 用 UPDATE ... SET 修改数据。