在拉勾教育大数据训练营的学习中,这个是的最开始的学习的,大数据的基础hadoop,讲的非常详细,对后面的学习理解也很有帮助
hadoop
1.简介
Hadoop 是一个适合大数据的分布式存储和计算平台。
狭义Hadoop=HDFS(分布式文件系统)+MapReduce(分布式计算框架)+Yarn(资源协调框架)+Common模块
HDFS:一个高可靠、高吞吐量的分布式文件系统,数据切割、制作副本、分散储存
MapReduce:一个分布式的离线并行计算框架,拆解任务、分散处理、汇整结果,MapReduce计算 = Map阶段 + Reduce阶段
Yarn:作业调度与集群资源管理的框架
Common:支持其他模块的工具模块(Configuration、RPC、序列化机制、日志操作)
发行版本:
企业中主要用到的三个版本分别是:Apache Hadoop版本(最原始的,所有发行版均基于这个版 本进行改进)、Cloudera版本(Cloudera’s Distribution Including Apache Hadoop,简称“CDH”)生产环境推荐、 Hortonworks版本(Hortonworks Data Platform,简称“HDP”)。
2.安装
参考课件,不做详细的说明
3.HDFS
3.1 HDFS的简介
HDFS 通过统一的命名空间目录树来定位文件; 另外,它是分布式的,由很多服务器联合起来实现 其功能,集群中的服务器有各自的角色(分布式本质是拆分,各司其职);
典型的Master/Slave 架构,分块存储(block机制),默认是128M,HDFS 支持传统的层次型文件组织结构。Namenode 负责维护文件系统的名字空间(命名空间),任何对文件系统名字空间或属性的修改都将被 Namenode 记录下来。我们把目录结构及文件分块位置信息叫做元数据。文件的各个 block 的具体存储管理由 DataNode 节点承担。一个block会有多个DataNode来存储,DataNode会定时向NameNode来汇报自己持有的block信息。为了容错,文件的所有 block 都会有副本。每个文件的 block 大小和副本系数都是可配置的。副本数量默认是3个。一次写入,多次读出
NameNode(nn):Hdfs集群的管理者,Master
存储文件的元数据,比如文件名、文件目录结构、文件属性(生成时间、副
本数、文件权限),以及每个文件的块列表和块所在的DataNode等。维护管理Hdfs的名称空间(NameSpace) 维护副本策略 记录文件块(Block)的映射信息 负责处理客户端读写请求
SecondaryNameNode(2nn):辅助NameNode更好的工作,用来监控HDFS状态的辅助后台
程序,每隔一段时间获取HDFS元数据快照。
DataNode:NameNode下达命令,DataNode执行实际操作,Slave节点。保存实际的数据块
负责数据块的读写 以及块数据的校验
Client:客户端上传文件到HDFS的时候,Client负责将文件切分成Block,然后进行上传 请求NameNode交互,获取文件的位置信息 读取或写入文件,与DataNode交互 Client可以使用一些命令来管理HDFS或者访问HDFS
3.2HDF客户端操作
略,参考项目
3.3HDFS的读操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v32pkEzz-1599125574934)(img/HDFSRead.png)]
-
客户端通过Distributed FileSystem向NameNode请求下载文件,NameNode通过查询元数据, 找到文件块所在的DataNode地址。
-
挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
-
DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
-
客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
3.4HDFS的写操作
3.5HDFS的元数据管理机制
第一阶段:NameNode启动
-
第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加 载编辑日志和镜像文件到内存。
-
客户端对元数据进行增删改的请求。
-
NameNode记录操作日志,更新滚动日志。
-
NameNode在内存中对数据进行增删改。
第二阶段:Secondary NameNode工作
-
Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否执 行检查点操作结果。
-
Secondary NameNode请求执行CheckPoint。
-
NameNode滚动正在写的Edits日志。
-
将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。
-
Secondary NameNode加载编辑日志和镜像文件到内存,并合并。
-
生成新的镜像文件fsimage.chkpoint。
-
拷贝fsimage.chkpoint到NameNode。
-
NameNode将fsimage.chkpoint重新命名成fsimage。
4.MapReduce
4.1MapReduce简介
MapReduce的思想核心是分而治之,MapReduce任务过程是分为两个处理阶段:
Map阶段:Map阶段的主要作用是“分”,即把复杂的任务分解为若干个“简单的任务”来并行处理。 Map阶段的这些任务可以并行计算,彼此间没有依赖关系。
Reduce阶段:Reduce阶段的主要作用是“合”,即对map阶段的结果进行全局汇总。
4.2Hadoop序列化
序列化主要是我们通过网络通信传输数据时或者把对象持久化到文件,需要把对象序列化成二进制的结 构。
Hadoop使用的是自己的序列化格式Writable,它比java的序列化serialization更紧凑速度更快。一 个对象使用Serializable序列化后,会携带很多额外信息比如校验信息,Header,继承体系等。
4.3MapTask
数据块:Block是HDFS物理上把数据分成一块一块。
切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。
MapTask的并行度,取决于切片的大小,我们默认切片的大小等于128M=nlock的大小。
4.4ReduceTask
Reduce大致分为copy、sort、reduce三个阶段,重点在前两个阶段。copy阶段包含一个 eventFetcher来获取已完成的map列表,由Fetcher线程去copy数据,在此过程中会启动两个merge线 程,分别为inMemoryMerger和onDiskMerger,分别将内存中的数据merge到磁盘和将磁盘中的数据 进行merge。待数据copy完成之后,copy阶段就完成了,开始进行sort阶段,sort阶段主要是执行 finalMerge操作,纯粹的sort阶段,完成之后就是reduce阶段,调用用户定义的reduce函数进行处理。
ReduceTask的并行度同样影响整个Job的执行并发度和执行效率,ReduceTask数量的决定是可以直接手动设置:
job.setNumReduceTasks(4);
注意事项
-
ReduceTask=0,表示没有Reduce阶段,输出文件数和MapTask数量保持一致;
-
ReduceTask数量不设置默认就是一个,输出文件数量为1个;
-
如果数据分布不均匀,可能在Reduce阶段产生倾斜;
4.5Shuffle机制
map阶段处理的数据如何传递给reduce阶段,是MapReduce框架中最关键的一个流程,这个流程就叫
shuffle。
shuffle: 洗牌、发牌——(核心机制:数据分区,排序,分组,combine,合并等过程)
4.5.1分区(Partitioner)
在MapReduce中,通过我们指定分区,会将同一个分区的数据发送到同一个reduce当中进行处理(默认 是key相同去往同个分区),默认使用HashPartitioner,保证了相同的key去往同个分区
自定义分区:
-
自定义类继承Partitioner,重写getPartition()方法
-
在Driver驱动中,指定使用自定义Partitioner
-
在Driver驱动中,要根据自定义Partitioner的逻辑设置相应数量的ReduceTask数量。
案例:数据 按照不同的appkey(或者其他某个字段)把记录输出到不同的分区中
总结
- 自定义分区器时最好保证分区数量与reduceTask数量保持一致;
- 如果分区数量不止1个,但是reduceTask数量1个,此时只会输出一个文件。
- 如果reduceTask数量大于分区数量,但是输出多个空文件
- 如果reduceTask数量小于分区数量,有可能会报错。
4.5.2combiner(预聚合)
- Combiner是MR程序中Mapper和Reducer之外的一种组件
- Combiner组件的父类就是Reducer
- Combiner和reducer的区别在于运行的位置
- Combiner是在每一个maptask所在的节点运行;
- Combiner的意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量。
- Combiner能够应用的前提是不能影响最终的业务逻辑,此外,Combiner的输出kv应该跟reducer的输入kv类型要对应起来。
直接使用Reducer作为Combiner组件来使用是可以的!!
4.6MapReduce中的排序
MapTask和ReduceTask均会对数据按照key进行排序。该操作属于Hadoop的默认行为。默认排序是按照字典顺序排序,且实现该排序的方法是 快速排序。
MapTask:溢写完毕后,它会对磁盘上所有文件进行归并排序。
ReduceTask:当所有数据拷贝完毕后,ReduceTask统-对内存和磁盘上的所有数据进行一次归并排 序。
-
部分排序. MapReduce根据输入记录的键对数据集排序。保证输出的每个文件内部有序。
-
全排序
最终输出结果只有一个文件,且文件内部有序。实现方式是只设置- -个ReduceTask。但该方法在 处理大型文件时效率极低,因为- -台机器处理所有文件,完全丧失了MapReduce所提供的并行架 构。 -
辅助排序: ( GroupingComparator分组) 在Reduce端对key进行分组。应用于:在接收的key为bean对象时,想让一个或几个字段相同(全部 字段比较不相同)的key进入到同一个reduce方法时,可以采用分组排序。
-
二次排序. 在自定义排序过程中,如果compareTo中的判断条件为两个即为二次排序。
Bean对象如果作为Map输出的key时,需要实现WritableComparable接口并重写compareTo方法指定 排序规则
全排序:
- 自定义对象作为Map的key输出时,需要实现WritableComparable接口,排序:重写 compareTo()方法,序列以及反序列化方法
- 再次理解reduce()方法的参数;reduce()方法是map输出的kv中key相同的kv中的v组成一个集合调 用一次reduce()方法,选择遍历values得到所有的key.
- 默认reduceTask数量是1个;
- 对于全局排序需要保证只有一个reduceTask!!
案例:基于统计的播放时长案例的输出结果对总时长进行排序
分区排序(默认的分区规则,区内有序)
GroupingComparator是mapreduce当中reduce端的一个功能组件,主要的作用是决定哪些数据作为 一组,调用一次reduce的逻辑,默认是每个不同的key,作为多个不同的组,每个组调用一次reduce逻 辑,我们可以自定义GroupingComparator实现不同的key作为同一个组,调用一次reduce逻辑。
案例:求出每一个订单中成交金额最大的一笔交易。
4.7MapReduce读取和输入数据
4.7.1 InputFormat
运行MapReduce程序时,输入的文件格式包括:基于行的日志文件、二进制格式文件、数据库表等。
InputFormat常见子类包括:
-
TextInputFormat (普通文本文件,MR框架默认的读取实现类型)
-
KeyValueTextInputFormat(读取一行文本数据按照指定分隔符,把数据封装为kv类型)
-
NLineInputF ormat(读取数据按照行数进行划分分片)
-
CombineTextInputFormat(合并小文件,避免启动过多MapTask任务)
-
自定义InputFormat
// 如果不设置InputFormat,它默认用的是TextInputFormat.class job.setInputFormatClass(CombineTextInputFormat.class);
//虚拟存储切片最大值设置4m
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);
注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值。
4.7.2OutputFormat
OutputFormat:是MapReduce输出数据的基类,所有MapReduce的数据输出都实现了OutputFormat 抽象类。下面我们介绍几种常见的OutputFormat子类
TextOutputFormat 默认的输出格式是TextOutputFormat,它把每条记录写为文本行。它的键和值可以是任意类型,
因为TextOutputFormat调用toString()方 法把它们转换为字符串。 SequenceFileOutputFormat
将SequenceFileOutputFormat输出作为后续MapReduce任务的输入,这是一种好的输出格式, 因为它的格式紧凑,很容易被压缩。
自定义OutputFormat
案例要在一个MapReduce程序中根据数据的不同输出两类结果到不同目录,这类输出需求可以通过自定义 OutputFormat来实现。
实现步骤
-
自定义一个类继承FileOutputFormat。
-
改写RecordWriter,改写输出数据的方法write()。
参考code
4.8 shuffle阶段数据压缩机制
数据压缩有两大好处,节约磁盘空间,加速数据在网络和磁盘上的传输!!
4.8.1hadoop支持压缩的算法
我们可以使用bin/hadoop checknative 来查看我们编译之后的hadoop支持的各种压缩算法,压缩格式:DEFLATE,Gzip,bzip2,LZO,Snappy的各种比较
4.8.2压缩的位置
Map输入端压缩
此处使用压缩文件作为Map的输入数据,无需显示指定编解码方式,Hadoop会自动检查文件扩展 名,如果压缩方式能够匹配,Hadoop就会选择合适的编解码方式对文件进行压缩和解压。
Map输出端压缩
Shuffle是Hadoop MR过程中资源消耗最多的阶段,如果有数据量过大造成网络传输速度缓慢,可以考虑使用压缩
Reduce端输出压缩
输出的结果数据使用压缩能够减少存储的数据量,降低所需磁盘的空间,并且作为第二个MR的输 入时可以复用压缩。
4.8.3压缩的配置
-
在驱动代码中通过Configuration直接设置使用的压缩方式
设置map阶段压缩 Configuration configuration = new Configuration(); configuration.set("mapreduce.map.output.compress","true"); configuration.set("mapreduce.map.output.compress.codec","org.apache.hadoop.i o.compress.SnappyCodec"); 设置reduce阶段的压缩 configuration.set("mapreduce.output.fileoutputformat.compress","true"); configuration.set("mapreduce.output.fileoutputformat.compress.type","RECORD" ); configuration.set("mapreduce.output.fileoutputformat.compress.codec","org.ap ache.hadoop.io.compress.SnappyCodec");
-
配置mapred-site.xml(修改后分发到集群其它节点,重启Hadoop集群),此种方式对运行在集群的 所有MR任务都会执行压缩。
5.Yarn
5.1 Yarn架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gAVQjiY5-1599125575004)(img/yarn.png)]
**ResourceManager(rm)😗*处理客户端请求、启动/监控ApplicationMaster、监控NodeManager、资 源分配与调度;
**NodeManager(nm)😗*单个节点上的资源管理、处理来自ResourceManager的命令、处理来自 ApplicationMaster的命令;
**ApplicationMaster(am)😗*数据切分、为应用程序申请资源,并分配给内部任务、任务监控与容错。
**Container:**对任务运行环境的抽象,封装了CPU、内存等多维资源以及环境变量、启动命令等任务运行相关的信息。
5.2Yarn任务提交
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6wO5tI2I-1599125575008)(img/yarntask.png)]
5.3Yarn调度策略
Hadoop作业调度器主要有三种:FIFO、Capacity Scheduler和Fair Scheduler。Hadoop2.9.2默认的资 源调度器是Capacity Scheduler。
容量调度器(Capacity Scheduler 默认的调度器)
Apache Hadoop默认使用的调度策略。Capacity 调度器允许多个组织共享整个集群,每个组织可 以获得集群的一部分计算能力。通过为每个组织分配专门的队列,然后再为每个队列分配一定的集 群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。除此之外,队列内 部又可以垂直划分,这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部, 资源的调度是采用的是先进先出(FIFO)策略。
Fair Scheduler(公平调度器,CDH版本的hadoop默认使用的调度器)
Fair调度器的设计目标是为所有的应用分配公平的资源(对公平的定义可以通过参数来设置)。公 平调度在也可以在多个队列间工作。举个例子,假设有两个用户A和B,他们分别拥有一个队列。 当A启动一个job而B没有任务时,A会获得全部集群资源;当B启动一个job后,A的job会继续运 行,不过一会儿之后两个任务会各自获得一半的集群资源。如果此时B再启动第二个job并且其它 job还在运行,则它将会和B的第一个job共享B这个队列的资源,也就是B的两个job会用于四分之 一的集群资源,而A的job仍然用于集群一半的资源,结果就是资源最终在两个用户之间平等的共 享