共计 8075 个字符,预计需要花费 21 分钟才能阅读完成。
一、时代背景
2000 年左右的时候,中国互联网尚处在门户时代,世界互联网曾经开始腾飞。
一方面,以 Google 为代表的支流互联网公司开始面临数据暴发的场景;另一方面,过后的互联网公司广泛抉择应用配置低下的便宜服务器。所以急剧减少的数据量与低下的计算存储能力之间的矛盾成为了过后的支流互联网公司面临的主要矛盾之一。
超级计算机尽管可能解决一部分大数据计算的问题,然而超级计算机价格昂扬,次要在实验室和科研机构中采纳。工业界尚没有一个对立的且失去宽泛商用的分布式计算框架,尽管过后曾经也钻研进去了一些分布式的计算框架,然而大部分都还停留在实验室或者科研机构外面。
没有失去推广的起因其实也比较简单,就是那些分布式框架设计的切实是太简单了,基本就没有方法被很好的了解,更不用说写代码去做实现和做分布式计算了。
二、Hadoop 的诞生
在这个时代背景下,咱们来看一下 Hadoop 是如何诞生的。
第一个工夫点是 2003 年的 11 月份,Google 发表了第一篇论文《The Google File System》,前面咱们简称 GFS。次要内容是如何解决分布式存储的问题。
第二个工夫节点是 2004 年 12 月份,Google 发表了第二篇论文《MapReduce:Simplified Data Processing on Large Clusters》。探讨的是在大规模集群下一种简化了的数据处理模型,前面咱们还会具体分析。
顺便提一下,在 2006 年的时候,Google 发表了第三篇论文,叫《Bigtable: A Distributed Storage System for Structured Data》。
这三篇论文的发表基本上就标记着整个大数据时代的降临,咱们个别也把它们称为是大数据畛域的三驾马车。第一篇论文解决的是分布式存储的问题;第二篇论文解决的是分布式计算的问题;第三篇论文解决的是大规模结构化数据的存储和查问问题。
Google 在发表这些论文之前外部曾经构建出了相应的零碎,而且在公司外部失去了宽泛的利用。同时 Google 是一家做搜索引擎的公司,外围问题是解决互联网的爬取和索引构建,当互联网上的数据特地大时,如何对这么多的数据疾速的构建索引,在 MapReduce 诞生之前 Google 外部各个部门的具体实现也都不统一,然而碰到的问题和大略的解决思路是相似的,比方如何进行多台机器的工作划分、如何进行容错,然而大家根本都在做一些反复造轮子的工作,而且实现和保护老本都很高。这时 Google 外部的大神 Jeff Dean 就基于大家的实际形象出了 MapReduce 的架构。
然而,Google 的这三篇论文和 Hadoop 有什么关系呢?这时就要提到第二个人 ——Doug Cutting,Doug Cutting 是一个开源零碎爱好者,和 Google 差不多同期也实现了一个开源版本的搜索引擎。
然而,他的引擎始终无奈做到 Google 这么快的搜寻和索引构建能力,当 Google 发表了这两篇论文之后,Doug Cutting 受到了启发,就实现了开源版本的 GFS 和 MapReduce。一开始做这两个零碎也次要是为了解决搜索引擎当中碰到的数据统计问题,然而人们很快发现,MapReduce 这个框架其实是很灵便而且十分通用的。
于是到 2006 年 2 月份,Hadoop 我的项目就正式成立了,它就蕴含了两个局部:一部分叫做 MapReduce,解决分布式计算的问题;另外一个局部叫做 HDFS,解决分布式存储的问题。
另外也提一下 Hadoop 这个名字是怎么来的,Doug Cutting 已经解释说这个名字其实是他儿子的一个毛绒玩具大象的名字,包含当初大家看到的 Hadoop 的黄色大象 Logo,其实也是来自于这个玩具大象的启发。不过当初咱们说玩转大数据的时候,经常说让大象能跳舞,也是在形象的强调 Hadoop 给大数据带来的灵便计算的能力。
三、HDFS 的特点
Hadoop 蕴含了 HDFS 和 MapReduce 两局部,咱们先来具体看一下 HDFS 是如何设计的,它有哪些特点呢?
第一个特点:谬误检测和主动复原机制是 HDFS 最外围的架构指标。为什么谬误复原会是过后的外围指标呢,这和过后的服务器配置也有很大关系,那个时候 Google 应用的典型服务器的配置可能是 2 核 4 G 内存这样一个配置,而且服务器很容易出故障,因为谷歌这种商业公司为了省钱往往应用便宜的商用服务器,甚至本人购买 CPU、内存、磁盘,本人组装服务器应用,这样组装进去的服务器可靠性是很低的。
而且在大规模集群下,这个故障率会被放大很多倍,咱们能够计算这样一道数学题:如果说咱们一台服务器出故障的概率是 1%,当咱们同时应用 100 台服务器的时候,至多有一台服务器出故障的概率是多少呢?答案是 63%,也就是咱们有少数机会碰到服务器故障的问题。当咱们应用的服务器资源进一步增多时,这个概率还会进一步减少。因而,谬误检测和故障复原是过后设计分布式系统时要思考的外围指标之一。
第二个特点是大规模的数据集,HDFS 上的典型文件大小在 GB ~ TB 级别。
第三个特点是流式的数据拜访,就是说咱们在读取 HDFS 上存储的数据时,个别是依照批量扫描的形式去读取,而不是随机性的拜访局部数据。
第四个特点是简略的一致性模型,咱们个别将数据一次性的写入 HDFS 上,后续可能会屡次读取数据做剖析,这是咱们高吞吐能力设计的重要前提之一。
最初一个特点是挪动计算比挪动数据更加划算,这也是一个十分外围的思维,一般来讲,通过网络去读取数据老本要远高于通过本地磁盘读取数据的老本,而后通过本地磁盘读取数据的老本要远高于通过本地内存读取数据的老本。所以挪动计算的思维是说,咱们尽量把这个计算放在数据所在的地位,而不是将数据拉取到咱们最终想要做计算的中央再对立解决,因为挪动数据老本很高,然而将计算放在数据所在的中央,就能够让计算本地化,这样是一种十分高效而划算的计算形式。
四、HDFS 数据块
HDFS 数据块(block)是 HDFS 的一个外围概念,数据块代表 HDFS 文件中读写的最小单位,典型的数据块大小在 64M 或者 128 M 左右。为什么须要引入数据块这个概念呢?
第一个起因是它能够最小化寻址空间。以机械磁盘为例,咱们晓得磁盘要读写数据的时候,先要通过磁臂的旋转找到对应的磁盘扇区,而后再通过磁头读写肯定的数据块,所以其中磁臂旋转寻找地位的过程是十分耗时的,如果数据块足够大,咱们将能够将数据间断的存储在一起,这样磁臂的寻址工夫就会大大减少,整个磁盘读写的效率也是最高的。
第二个起因是在咱们引入了数据块的概念之后,HDFS 自身的文件大小,就能够间接看做有多少个数据块组成,实践上 HDFS 文件能够是无限大的。
第三个起因是在咱们设计存储子系统的时候,整个架构也能够更加的简洁,咱们只须要把服务器磁盘看做是一个个的数据块就能够了。
最初一个起因是咱们在做数据的正本治理和容错时,也都是依照数据块为单位的,当咱们一个数据块失落或者损坏时,只须要对这当个的数据块进行修复就能够了,不会导致整个文件的损坏。
五、HDFS 整体架构
HDFS 的整体架构如图所示。HDFS 外部分为了两种角色:一种角色叫做 NameNode,另一种角色叫做 DataNode。在一个典型的 HDFS 集群当中,个别会有一个工作的 NameNode 和多个工作的 DataNode,所以它是一个典型的主从架构。
NameNode 会保护所有的元数据,这些元数据次要是指的是 HDFS 文件名、目录构造以及每个 HDFS 文件对应的文件块的实在存储地位等信息。
DataNode 节点个别在每台存储服务器上都会部署一个,次要负责管理存储在这台服务器上的文件的读写。比如说当咱们去读取一个文件的时候,咱们先去 NameNode 上申请文件的地位,再去对应的 DataNode 节点上读取理论的文件数据。写文件的时候也是相似,咱们先申请 NameNode 调配对应的 DataNode 节点和地位信息,而后再去 DataNode 节点上写入数据。
这里还有一个概念是机架,在一个大的 HDFS 集群中,读写数据都会思考机架的影响,因为同一个机架往往对应着同一个交换机,如果读文件的时候,在同机架的机器上进行读取就会缩小两头的网络传输。
反过来,写文件的时候在同一个机架下面写也会更加高效。然而同一个交换机的限度也会导致同一个机架一起呈现故障的概率会比拟高,因而在写文件的时候除了要思考效率,还要兼顾文件的可靠性。
5.1 HDFS 读文件的过程
如图所示,当咱们应用 HDFS 读取文件的时候,咱们的客户端要做 1、3、6 这三个步骤。第 1 步,咱们应用 open 操作关上一个文件;而后第 3 步应用 read 操作读取文件的内容;等咱们读取完文件的内容之后,咱们在第 6 步应用 close 操作敞开文件。
从使用者的角度来看,这和读取一个本地文件简直没有任何区别,然而背地的执行过程是齐全不同的。当第 1 步 open 操作执行之后,HDFS 客户端就会向 NameNode 发动一个申请去获取指定文件的理论存储地位信息,当 read 操作发动之后,HDFS 就会间接去拜访对应的 DataNode 的数据,这时候就不再须要和 NameNode 打交道了,读取文件的时候,因为数据可能存储在多个 DataNode 上,客户端会顺次从多个 DataNode 节点上读取数据。读取实现之后咱们会将文件管道 close 掉,这时候一个残缺的 HDFS 文件读取过程就实现了。
5.2 HDFS 写文件的过程
咱们再来看一下 HDFS 写文件的过程,和读文件比拟相似,写文件的时候从操作者的角度看也是分成 3 步。第 1 步,咱们执行 create 操作创立一个文件。而后第 2 步,咱们执行 write 操作不停的写入文件内容。第 3 步,在咱们写入实现之后执行 close 操作将整个管道敞开。
前面理论产生了哪些事件呢?
首先客户端会向 NameNode 发动一个申请,NameNode 会查看客户端是否领有相应的权限,查看通过后会调配相应的 DataNode 以及对应的地位信息,通知客户端去哪里存储文件,客户端获取到这些信息之后,就会去对应的 DataNode 节点上写文件,在第一个 DataNode 节点上写完一个文件块之后,第一个 DataNode 节点还会把数据同步给第二个 DataNode 节点,同样的第二个节点还会把数据同步给第三个 DataNode 节点。
等数据写完之后,第三个节点会将确认音讯回传给第二个节点,第二个节点回传给第一个节点,第一个节点将最终的确认音讯回传给客户端确认数据写入实现。客户端会再向 NameNode 发送一个音讯,通知 NameNode 去更新相应的元数据信息。
这里为了保证数据的高可用,HDFS 也做了很多的容错机制,外围机制是正本机制。正本机制会保障默认状况下所有的数据都会依照 3 正本的形式进行存储,而且正本的存储地位也很有考究,第一个节点个别会抉择在客户端所在的机器存储第一个正本;而后抉择和第一个节点在同一个机架上的另外一个节点下面存储第二个正本;最初抉择和前两个节点在不同机架上的节点存储第三个正本。
这种抉择一方面是思考了存储数据的效率,另一方面也是为了尽可能的兼顾不同正本的可用性。另外 HDFS 在写文件的时候还会在本地提供 checksum 校验码机制,只有当所有节点上的数据的校验码统一才会认为数据被写入胜利了,从而保障写入过程中的可用性。
六、MapReduce 基本原理
通过 HDFS 咱们解决了分布式存储的问题,上面咱们再来看一下 Hadoop 的另一个重要组成部分 MapReduce。
MapReduce 次要用来解决分布式计算的问题,它的第一个核心思想是分治法,就是将一个大的工作分成若干个雷同的小工作,实现这些小的工作就相当于实现了这个大的工作。
第二个思维是挪动计算而不是挪动数据,这个思维咱们在前边介绍 HDFS 的设计思维时也提过,目标是为了尽量让计算本地化。
第三个思维就是容忍局部节点故障,这个咱们在 HDFS 局部也介绍过,在大规模集群在下硬件故障是十分广泛的事件,所以咱们的计算框架层面肯定要可能容忍这种局部节点的故障。
基于这三个根本思维咱们能够看一下这面这个具体的例子:如果咱们想要统计一篇文章中各个单词呈现的频率,咱们要怎么来实现呢?在不思考大数据量的状况下,咱们能够写一个简略的脚本就能实现,当初咱们假如想要依照上面示例的伪代码的办法散布两个步骤来实现。
在第一个函数 map 外面,咱们次要做的事件是把一篇文章按行读入进来,而后依照单词进行切割,切割实现之后间接输入每个单词,以及前面呈现的次数 1。
在第二个函数 reduce 外面,咱们输出的是 map 的输入,不过曾经把雷同的单词聚合到了一起,这时候,咱们只须要对每个单词,迭代累加前面单词呈现的次数就能够算出最终每个单词呈现的次数。
这个例子的计算过程非常简单,当初如果咱们把场景换成一个大数据量下的场景,要计算的文档的数据量可能是 TB 级别的,数据也可能是存储在多台机器上的,那咱们怎么来实现 WordCount 的计算呢?咱们就联合 MapReduce 的具体执行过程来看看。
咱们假如大数据量文档文件曾经存储在 HDFS 下面,当初咱们把文件宰割成 4 块,对应图中的 split1 – split4,其中的每个 map 工作会输出其中的一块文档数据,map 会依照咱们下面的代码示例对文档的内容进行宰割而后输入对应的 Key-Value 对,Key 就是咱们要统计的单词,Value 是这个单词呈现的次数,在 map 输入时 Value 值固定为 1。
map 输入的内容会进行分区并存储在本地磁盘下面,分区的目标是为了决定 map 输入的这部分内容会对应的发送给哪一个 reduce 进行解决。图中的黄色分区 1 内的数据最终都会发送给 reduce 1 作为输出。
reduce 的输出会是 Key-List<Value>,其中 Key 和 map 输入的 key 雷同,List<Value> 是所有 map 输入的 value 的汇合,在 reduce 阶段,咱们对汇合内的 value 反复累加就能够最终计算出想要的统计解决,reduce 的输入最终还会写入到 HDFS 存储系统当中。
在 map 的输入到 reduce 的输出这两头的过程咱们称之为 Shuffle,Shuffle 的过程波及到数据的排序和从新散发,是整个 MapReduce 最外围也是最简单的过程。其中在 map 输入数据的时候一方面要对数据进行分区,同时在同一个分区内的数据还会依照 Key 进行排序。
map 阶段实现之后,reduce 会去对应的 map 工作的输入目录下拉取对应分区内的数据,同时 reduce 阶段为了保障多个 map 的输入后果是最终有序的还须要在输出阶段做一次归并排序。从整个 MapReduce 的执行过程中咱们能够看到,如果是 map 阶段工作产生了失败,那只须要从新执行单个 map 工作,咱们能够抉择在任意一台节点下面从新读取对应分片的数据,从新将后果输入到本地磁盘。如果是 reduce 阶段工作产生了失败,那只须要执行单个 reduce 工作,同样的 reduce 工作也能够抉择在任意一台新节点下面进行执行,从新去对应的 map 输入地位下拉取对应分区的数据,统计最终的计算结果并输入到磁盘当中。
七、Yarn 作业调度过程
前边咱们介绍了 MapReduce 的基本原理和次要执行过程,其中还有一个很重要的局部是多个 map 和 reduce 的工作是如何调配的不同的节点上执行的,工作之间的协调工作又是如何做的呢,这里要引入 Yarn 的概念。
Yarn 是从 Hadoop 2 开始引入的新组件,次要用来解决工作资源管理和调配的问题。Yarn 外部也分为两种角色,ResourceManager 和 NodeManager。ResourceManager 次要用来协调 NodeManger 做全局的资源管理和调配。NodeManager 对应一个具体的执行节点,负责管理调度到该节点上的工作实例。一个典型的 MapReduce 作业执行调度的过程如上图所示:
(1)客户端启动 MapReduce 作业。
(2)客户端向 ResourceManager 发送申请,申请一个新的 Application id。
(3)客户端将执行作业所须要的代码和配置文件等本地资源拷贝到 HDFS 等分布式存储系统上。
(4)客户端再次向 ResourceManager 发送提交作业申请。
(5)ResourceManager 找到一个绝对闲暇的 NodeManager,由这台 NodeManager 启动一个容器,在这个容器内会启动 AppMaster 工作。
(6)AppMaster 会作为这个 MapReduce 作业生命周期内的管理中心,首先对作业进行初始化。
(7)AppMaster 去 HDFS 上获取作业的执行资源,计算出相应的分片信息,这时就能够晓得这个 MapReduce 程序肯定须要多少执行资源。
(8)AppMaster 向 ResourceManager 申请调配执行资源,这里的执行资源次要值得是 CPU 和内存等硬件资源,在 Yarn 外面理论是以 Container 为载体进行调配的。
(9)AppMaster 申请到相应的资源信息之后,就会去对应的 NodeManager 节点上启动相应的 Container 容器。
(10)NodeManager 启动新的 Container 容器并获取执行作业所须要的代码和分片配置等信息。
(11)在容器内真正开始执行一个 Map 或者 Reduce 的工作。
这里值得一提的是 Yarn 作为独立的组件,定位曾经是一个通用的资源管理和协调核心,所以 Yarn 下面不仅可能执行 MapReduce 作业,对于新的 Spark 的作业和 Flink 的作业等也都反对了提交到 Yarn 下面进行治理和执行。
八、Hadoop 生态系统
后面咱们介绍了 Hadoop 的两个外围局部:HDFS 解决了分布式存储的问题,MapReduce 解决了分布式计算的问题,最初还介绍了 Yarn 作为独立的资源管理和协调核心在 Hadoop 2 外面被引入。
在这些根底组件之上,整个开源生态圈围绕 Hadoop 根底组件又开发进去了越来越多的新组件,解决在大数据处理过程中碰到的各种各样的问题。当初当咱们再泛泛地议论 Hadoop 的时候,往往指的是整个 Hadoop 生态系统,这外面蕴含了越来越多的性能组件。
就拿最近比拟炽热的 Spark 和 Flink 来说,Spark 和 Flink 都是为了解决分布式计算的问题而诞生的,所以它们定位的地位是和 MapReduce 在同一个级别的。Spark 和 Flink 读取和输入的文件个别也都是存储在 HDFS 下面,Spark 和 Flink 作业个别也都能够在 Yarn 下面被执行和调度。
MapReduce 失去广泛应用之后,人们也发现了它存在着两个外围的短板:一个是 MapReduce 执行效率很低,只适宜做离线计算,不适宜用在时效性要求很高的计算场景;另一个是 MapReduce 架构过于简略,只反对 Map 和 Reduce 两个算子,很多简单的计算操作都很难间接基于这两个算子进行实现。
而且 MapReduce 提供的是比拟底层的 API 接口,依赖于程序开发中要去了解比拟多的分布式相干的常识。一方面在 MapReduce 的根底上人们做了很多的修补性的工作,比方引入了 Hive;另一方面是呈现了更多的新型计算框架,这外面卓越的就是 Spark 和 Flink。Spark 和 Flink 不仅大大提高了计算的性能问题,更是在流批一体、机器学习、SQL 查问等方面做到了底层架构的对立,裸露进去的是更多高级的下层 API,对于大数据程序开发者来讲也会更加敌对。
尽管 MapReduce 会被 Spark、Flink 等新型计算框架逐步代替,然而 MapReduce 的根本思维是失去了继承和发挥的,对于了解任何一个分布式计算零碎来说了解分明 MapReduce 的执行过程都是根底之一。
同时,Hadoop 作为大数据生态圈的底层根底以及围绕着 HDFS、Yarn 等开发进去的一系列分布式数据处理系统也让整个 Hadoop 生态圈变得越来越欠缺和沉闷。Hadoop 的根底原理和利用也是值得咱们每个入门大数据的同学进行学习和思考的内容。谢谢大家。
文渣起源:公众号神策技术社区