(一)简介
1.Apache Hadoop软件库是一个框架,允许在集群服务器上使用简单的编程模型对大数据集进行分布式处理;Hadoop被设计成能够从单台服务器扩展到数以千计的服务器,每台服务器都有本地的计算和存储资源;Hadoop的高可用性并不依赖硬件,其代码库自身就能在应用层侦测并处理硬件故障,因此能基于服务器集群提供高可用性的服务;
2.Hadoop生态系统如下:
- HDFS--Hadoop生态圈的基本组成部分是Hadoop分布式文件系统(HDFS);HDFS是一种数据分布式保存机制,数据被保存在计算机集群上,HDFS为HBase等工具提供了基础;
- MapReduce--Hadoop的主要执行框架是MapReduce,它是一个分布式、并行处理的编程模型,MapReduce把任务分为map(映射)阶段和reduce(化简);由于MapReduce工作原理的特性,Hadoop能以并行的方式访问数据,从而实现快速访问数据;
- Hbase--HBase是一个建立在HDFS之上,面向列的NoSQL数据库,用于快速读/写大量数据;HBase使用Zookeeper进行管理,确保所有组件都正常运行;
- Zookeeper--用于Hadoop的分布式协调服务。Hadoop的许多组件依赖于Zookeeper,它运行在计算机集群上面,用于管理Hadoop操作;
- Pig--它是MapReduce编程的复杂性的抽象。Pig平台包括运行环境和用于分析Hadoop数据集的脚本语言(Pig Latin);其编译器将Pig Latin翻译成MapReduce程序序列;
- Hive--Hive类似于SQL高级语言,用于运行存储在Hadoop上的查询语句,Hive让不熟悉MapReduce开发人员也能编写数据查询语句,然后这些语句被翻译为Hadoop上面的MapReduce任务;像Pig一样,Hive作为一个抽象层工具,吸引了很多熟悉SQL而不是Java编程的数据分析师;
- Sqoop是一个连接工具,用于在关系数据库、数据仓库和Hadoop之间转移数据;Sqoop利用数据库技术描述架构,进行数据的导入/导出;利用MapReduce实现并行化运行和容错技术;
- Flume提供了分布式、可靠、高效的服务,用于收集、汇总大数据,并将单台计算机的大量数据转移到HDFS;它基于一个简单而灵活的架构,并提供了数据流的流;它利用简单的可扩展的数据模型,将企业中多台计算机上的数据转移到Hadoop;
- Apache Hadoop YARN (Yet Another Resource Negotiator,另一种资源协调者)是一种新的 Hadoop 资源管理器,它是一个通用资源管理系统,可为上层应用提供统一的资源管理和调度,它的引入为集群在利用率、资源统一管理和数据共享等方面带来了巨大好处;
3.三种安装模式
(1)单机模式:单机模式是Hadoop的默认模式;当首次解压Hadoop的源码包时,Hadoop无法了解硬件安装环境,便保守地选择了最小配置;在这种默认模式下所有3个XML文件均为空;当配置文件为空时,Hadoop会完全运行在本地;因为不需要与其他节点交互,单机模式就不使用HDFS,也不加载任何Hadoop的守护进程;该模式主要用于开发调试MapReduce程序的应用逻辑;
(2)伪分布模式:伪分布模式在“单节点集群”上运行Hadoop,其中所有的守护进程都运行在同一台机器上;该模式在单机模式之上增加了代码调试功能,允许你检查内存使用情况,HDFS输入输出,以及其他的守护进程交互;
(3)全分布模式:Hadoop守护进程运行在一个集群上;
4.五种守护进程
(1)NameNode:Hadoop 中的主服务器,管理文件系统名称空间和对集群中存储的文件的访问;
(2)SecondaryNameNode:提供周期检查点和清理任务;
(3)DataNode:负责管理连接到节点的存储(一个集群中可以有多个节点);每个存储数据的节点运行一个 datanode 守护进程;
(4)JobTracker和TaskTracker:JobTracker负责调度 DataNode上的工作;每个 DataNode有一个TaskTracker,它们执行实际工作;JobTracker和 TaskTracker采用主-从形式,JobTracker跨DataNode分发工作,而 TaskTracker执行任务;JobTracker还检查请求的工作,如果一个 DataNode由于某种原因失败,JobTracker会重新调度以前的任务;
5.Hadoop是使用Java语言编写的,所以最直接的方式的就是使用Java语言来实现Mapper和Reducer,然后配置MapReduce Job,提交到集群计算环境来完成计算。但是很多开发者可能对Java并不熟悉,而是对一些具有脚本特性的语言,如C++、Shell、Python、 Ruby、PHP、Perl有实际开发经验,Hadoop Streaming为这一类开发者提供了使用Hadoop集群来进行处理数据的工具,即工具包hadoop-streaming-.jar;
(二)HDFS
1.HDFS(Hadoop Distributed File System)是一个分布式文件系统,是谷歌的GFS山寨版本;它具有高容错性并提供了高吞吐量的数据访问,非常适合大规模数据集上的应用,它提供了一个高度容错性和高吞吐量的海量数据存储解决方案;
- 高吞吐量访问:HDFS的每个Block分布在不同的Rack上,在用户访问时,HDFS会计算使用最近和访问量最小的服务器给用户提供;由于Block在不同的Rack上都有备份,所以不再是单数据访问,所以速度和效率是非常快的。另外HDFS可以并行从服务器集群中读写,增加了文件读写的访问带宽;
- 高容错性:系统故障是不可避免的,如何做到故障之后的数据恢复和容错处理是至关重要的;HDFS通过多方面保证数据的可靠性,多份复制并且分布到物理位置的不同服务器上,数据校验功能、后台的连续自检数据一致性功能都为高容错提供了可能;
- 线性扩展:因为HDFS的Block信息存放到NameNode上,文件的Block分布到DataNode上,当扩充的时候仅仅添加DataNode数量,系统可以在不停止服务的情况下做扩充,不需要人工干预;
2.HDFS架构
- NameNode:在Hadoop1.X中只有一个Master节点,管理HDFS的名称空间和数据块映射信息、配置副本策略和处理客户端请求;
- Secondary NameNode:辅助NameNode,分担NameNode工作,定期合并fsimage和fsedits并推送给NameNode,紧急情况下可辅助恢复NameNode;
- DataNode:Slave节点,实际存储数据、执行数据块的读写并汇报存储信息给NameNode;
- DataNode中文件的最小单元为block,一个block通常为64M,默认保存3份;
-
hadoop的集群是基于master/slave模式,namenode和jobtracker属于master,datanode和tasktracker属于slave,master只有一个,而slave有多个;
-
SecondaryNameNode内存需求和NameNode在一个数量级上,所以通常secondary NameNode(运行在单独的物理机器上)和NameNode运行在不同机器上;
-
JobTracker 对应于 NameNode,TaskTracker 对应于 DataNode;DataNode 和NameNode 是针对数据存放来而言的;JobTracker和TaskTracker是对于MapReduce执行而言的;
(三)MapReduce
3.1 简介
MapReduce 是现今一个非常流行的分布式计算框架,它被设计用于并行计算海量数据。第一个提出该技术框架的是Google 公司,而Google 的灵感则来自于函数式编程语言,如LISP,Scheme,ML 等。MapReduce 框架的核心步骤主要分两部分:Map 和Reduce。当你向MapReduce 框架提交一个计算作业时,它会首先把计算作业拆分成若干个Map 任务,然后分配到不同的节点上去执行,每一个Map 任务处理输入数据中的一部分,当Map 任务完成后,它会生成一些中间文件,这些中间文件将会作为Reduce 任务的输入数据。Reduce 任务的主要目标就是把前面若干个Map 的输出汇总到一起并输出。从高层抽象来看,MapReduce的数据流图如下图所示:
3.2 mapreduce流程分析
(1)map过程:
- 每个输入分片会让一个map任务来处理,默认情况下,以HDFS的一个块的大小(默认为64M)为一个分片,当然我们也可以设置块的大小。map输出的结果会暂且放在一个环形内存缓冲区中(该缓冲区的大小默认为100M,由io.sort.mb属性控制),当该缓冲区快要溢出时(默认为缓冲区大小的80%,由io.sort.spill.percent属性控制),会在本地文件系统中创建一个溢出文件,将该缓冲区中的数据写入这个文件;
- 在写入磁盘之前,线程首先根据reduce任务的数目将数据划分为相同数目的分区,也就是一个reduce任务对应一个分区的数据。这样做是为了避免有些reduce任务分配到大量数据,而有些reduce任务却分到很少数据,甚至没有分到数据的尴尬局面。其实分区就是对数据进行hash的过程。然后对每个分区中的数据进行排序,如果此时设置了Combiner,将排序后的结果进行Combia操作,这样做的目的是让尽可能少的数据写入到磁盘;
-
当map任务输出最后一个记录时,可能会有很多的溢出文件,这时需要将这些文件合并。合并的过程中会不断地进行排序和combia操作,目的有两个:
- 尽量减少每次写入磁盘的数据量
- 尽量减少下一复制阶段网络传输的数据量。最后合并成了一个已分区且已排序的文件。为了减少网络传输的数据量,这里可以将数据压缩,只要将mapred.compress.map.out设置为true就可以了
-
将分区中的数据拷贝给相对应的reduce任务。有人可能会问:分区中的数据怎么知道它对应的reduce是哪个呢?其实map任务一直和其父TaskTracker保持联系,而TaskTracker又一直和JobTracker保持心跳。所以JobTracker中保存了整个集群中的宏观信息。只要reduce任务向JobTracker获取对应的map输出位置就可以了
(2)reduce过程:
- Reduce会接收到不同map任务传来的数据,并且每个map传来的数据都是有序的。如果reduce端接受的数据量相当小,则直接存储在内存中(缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对数据合并后溢写到磁盘中;
- 随着溢写文件的增多,后台线程会将它们合并成一个更大的有序的文件,这样做是为了给后面的合并节省时间。其实不管在map端还是reduce端,MapReduce都是反复地执行排序,合并操作;
- 合并的过程中会产生许多的中间文件(写入磁盘了),但MapReduce会让写入磁盘的数据尽可能地少,并且最后一次合并的结果并没有写入磁盘,而是直接输入到reduce函数。
- 在集群中的任意一个节点提交MapReduce程序;
- JobClient收到作业后,JobClient向JobTracker请求获取一个Job ID;
- 将运行作业所需要的资源文件复制到HDFS上(包括MapReduce程序打包的JAR文件、配置文件和客户端计算所得的输入划分信息),这些文件都存放在JobTracker专门为该作业创建的文件夹中,文件夹名为该作业的Job ID;
- 获得作业ID后,提交作业;
- JobTracker接收到作业后,将其放在一个作业队列里,等待作业调度器对其进行调度,当作业调度器根据自己的调度算法调度到该作业时,会根据输入划分信息为每个划分创建一个map任务,并将map任务分配给TaskTracker执行;
- 对于map和reduce任务,TaskTracker根据主机核的数量和内存的大小有固定数量的map槽和reduce槽。这里需要强调的是:map任务不是随随便便地分配给某个TaskTracker的,这里有个概念叫:数据本地化(Data-Local)。意思是:将map任务分配给含有该map处理的数据块的TaskTracker上,同时将程序JAR包复制到该TaskTracker上来运行,这叫“运算移动,数据不移动”;
- TaskTracker每隔一段时间会给JobTracker发送一个心跳,告诉JobTracker它依然在运行,同时心跳中还携带着很多的信息,比如当前map任务完成的进度等信息。当JobTracker收到作业的最后一个任务完成信息时,便把该作业设置成“成功”。当JobClient查询状态时,它将得知任务已完成,便显示一条消息给用户;
- 运行的TaskTracker从HDFS中获取运行所需要的资源,这些资源包括MapReduce程序打包的JAR文件、配置文件和客户端计算所得的输入划分等信息;
- TaskTracker获取资源后启动新的JVM虚拟机;
- 运行每一个任务;
PS:Spark简介
1.概念:Spark拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的是Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce的算法;
2.Spark节点:
1)Spark节点分为驱动器(driver)跟执行器(executor);
2)驱动器节点的作用:执行程序中的main()方法的进程,它执行用户编写的用来创建SparkContext(初始化)、创建RDD,以及运行RDD的转化操作和行动操作的代码;负责把用户程序转化为多个物理执行单元;在各个执行器节点进程间协调任务的调度;
3)执行器节点的作用:负责运行组成Spark应用的任务,并将结果返回给驱动器进程;通过自身的块管理器(blockManager)为用户程序中要求缓存的RDD提供内存式存储,RDD是直接缓存在执行器进程内的,因此任务可以在运行时充分利用缓存数据加快运算;
3.Spark原理:
(1)每个Spark应用都由一个驱动器程序来发起集群上的各种并行操作;驱动器程序包含应用的main函数,并且定义了集群上的分布式数据集,以及对该分布式数据集应用了相关操作;
(2)驱动器程序通过一个SparkContext对象来访问Spark,这个对象代表对计算集群的一个连接(比如在sparkshell启动时已经自动创建了一个SparkContext对象,是一个叫做sc的变量);
ps:在初始化SparkContext的同时,可以通过加载sparkConf对象来加载集群的配置;
(3)一旦创建了sparkContext,就可以用它来创建RDD;比如调用sc.textFile()来创建一个代表文本中各行文本的RDD并执行相关操作:
val linesRDD = sc.textFile(“yangsy.text”)
val spark = linesRDD.filter(line=>line.contains(“spark”),spark.count())
执行这些操作,驱动器程序一般要管理多个执行器,就是我们所说的executor节点;
4.RDD介绍:
(1)RDD(Resilient DistributedDatasets)弹性分布式数据集,是分布式内存的一个抽象概念,RDD提供了一种高度受限的共享内存模型,即RDD是只读的记录分区的集合;对开发者而言,RDD可以看作是Spark的一个对象,它本身运行于内存中;
(2)RDD支持两种类型的操作:转化操作和行动操作: