为什么要有Hadoop?
结构的数据,并且这些海量的数据存储和检索就成为了一大问题。
Hadoop就是为了解决这些问题而出现的。
Hadoop的诞生
Doug Cutting等人就去研究这三篇论文,发现价值巨大,于是Doug Cutting等人在Nutch上实现了GFS和Map-Reduce,使得Nutch的性能飙升。
这三篇论文对应Hadoop的组件:
什么是Hadoop?
技术生态圈之一。
Hadoop发行版本
1、Apache版本最原始的版本
2、Clodera版本,在大型互联网企业中用的比较多,软件免费,通过服务收费。
3、Hortonworks文档比较好
特点
高可靠:维护多个副本,假设计算元素和存储出现故障时,可以对失败节点重新分布处理
高扩展:在集群间分配任务数据,可方便的扩展数以千计的节点
高效性:并行工作
高容错:自动保存多个副本,并且能够对失败任务重新分配
Hadoop组成
HDFS:一个高可靠高吞吐量的分布式文件系统
:存储文件的元数据,如:文件名、文件目录结构等信息
DataNode(dn):在文件系统存储文件块数据,以及数据的校验和,也就是真正存储文件内容的,只是文件大的时候会切割成一小块一小块的。
SecondayNameNode(2nn):用于监控HDFS状态的辅助后台程序,每隔一段时间就获取HDFS的快照,就是备份和监控状态
Yarn:作业调度与集群资源管理框架。(Hadoop2.0加入)
:处理客户端请求、启动和监控MRAppMaster、监控NodeManager,以及资源分配和调度。
:单个节点上的资源管理、处理来自ResourceManager的命令,处理来自MRAppMaster的命令。
MRAppMaster:数据切分、为应用程序申请资源,并分配内部任务、任务监控和容错。
Container:对任务运行环境的抽象,封装了CPU、内存等多维资源以及环境变量、启动命令等任务运行相关信息(hadoop内部文件操作命令和Liunx差不多)
MapReduce:分布式离线并行计算框架。
阶段:并行处理数据
阶段:对Map阶段处理的结果数据进行汇总
Common:支持其他模块的工具模块。
理解Hadoop组成
Hadoop内为什么要如此划分?
数据存放在Hadoop,那么Hadoop必然需要对数据进行管理,如果没有一个专门管理数据存储的组件或数据运算的组件,全部都融合在一个东西里面就会显得很臃肿,并且组件之间只需要通过接口进行沟通,那么各自的组件就可以仅仅自身的需求做优化等,那么就不会影响到其他的组件。
各自的组件只需要做好自己的事情,对外提供接口接收相应的数据及返回数据,只要符合我组件规范的就运行,不符合就不运行,而不需要关心其他,专心做自己的事情,也可以使得组件之间可以单独的运行。
HadoopĿ¼
bin:程序级命令(hdfs、Yarn等)
etc:配置文件
include:类库等文件
lib:类库等文件
libexec:类库等文件
sbin:hadoop系统命令(关闭、启动等)
share:官方提供的案例等
Hadoop运行模式
本地模式:不需要启动单独进程,直接运行,一般测试和开发使用,一台机器就可以运行,如果是在Liunx,跑的是本地,可以直接通过命令运行相应的jar包。
伪分布式模式:等同于分布式,但只有一个节点,具有集群的配置信息和运行,由于伪分布式只有一台机器,可以不启动Yarn,那么也就算是Hadoop的HDFS启动了,直接运行MapReduce程序的话,结果都在HDFS上,不在是在本地,如果需要交由YARN上进行资源调度和分配任务,则需要配置Yarn地址,以及指定数据获取方式。
完全分布式模式:多个节点一起运行,可以指定不同节点干不同的活,比如机器1干NameNode的活,机器2干ResourceManger的活。
注意:启动NameNode时,DataNode会记录NameNode信息(id),当缓存的NameNode记录删除了,这个时候启动就会报错,这个时候就需要将NameNode格式化(删除所有数据),之后在重新启动。
HDFS
HDFS是什么?
特点
低成本:由于是众多服务器组成的,那么在某服务器挂了,只需要付出一台廉价的服务器。
高容错性:HDFS是由众多服务器实现的分布式存储,每个文件都会有冗余备份,那么如果存储数据的某个服务器挂了,那么还有备份的数据,允许服务器出现故障。
高吞吐量:HDFS是一次写多次读的访问模型,不允许修改文件,并简化了数据的一致性问题。
就近原则:在数据附近执行程序,也体现出来移动计算比移动数据效率高。
可移植性:HDFS可以实现不同平台之间的移植。
应用场景
HDFS数据块
(标准:寻址时间只占传输时间的1%),如果块设置的够大,从磁盘传输数据的时间明显就大于定位这个块开始位置所需要的文件,因此传输一个由多个块组成的文件的时间取决于磁盘传输速率。
HDFS常用命令(和Liunx差不多)
基本命令:hadoop fs
查看帮助:hadoop fs 或 hadoop fs -help(详情)
创建目录:hadoop fs -mkdir /usr
查看目录信息:hadoop fs -ls /usr
本地剪切,粘贴到集群:hadoop fs -moveFromLocal test.txt /usr/
追加一个文件到已存在文件的末尾:hadoop fs -appendToFile test2.txt /usr/test.txt
显示文件内容:hadoop fs -cat /usr/test.txt
显示一个文件末尾:hadoop fs -tail /usr/ test.txt
以字符形式打印一个文件内容:hadoop fs -text /usr/test.txt
修改文件所属权限(-chgrp、-chomd、chown)(liunx一样用法): hadoop fs -chmod 777 /usr/test.txt
从本地复制到hdfs:hadoop fs -copyFormLocal text.txt /usr/test
hdfs复制到本地:hadoop fs -copyToLocal /usr/ text.txt ./
从hdfs路径拷贝到hdfs另一个路径:hadoop fs -cp /usr/dir1 /usr/dir2
在hdfs目录中移动文件:hadoop fs -mv /usr/test.txt /usr/dir
从hdfs下载文件到本地:hadoop fs -get /usr/test.txt ./
合并下载多个文件:hadoop fs -getmerge /usr /*.txt ./result.txt
上传文件等于copyFormLocal:hadoop fs -put test.txt /usr
删除文件或文件夹:hadoop fs -rmr /usr/test.txt
删除空目录:hadoop fs -rmdir /usr/test3
统计文件系统可用空间信息(-h格式化信息):hadoop fs -df -h
统计文件夹大小信息:hadoop fs -du -h /
统计制定目录下的文件节点数据量(嵌套级,当前文件个数,大小):hadoop fs -count -h /usr
设置文件的副本数:hadoop fs -setrep 3 /usr/test.txt
NameNode
NameNode和SecondaryNameNode工作机制
第一阶段:NameNode的工作
第二阶段:Secondary NameNode的工作
说明
Fsimage文件:HDFS文件系统元数据的一个永久检查点,其中包含HDFS文件系统所有目录和文件,以及node序列化信息。
Edits文件:存放HDFS文件系统的所有更新操作,文件系统客户端执行的所有写操作日志都会记录到edits文件。
Secondary NameNode:在主NameNode挂了,可以从Secondary NameNode中恢复数据,但是由于同步的条件限制,会出现数据不一致。
DataNode
工作机制
集群安全模式
只可读。
安全模式的应用场景
Java操作HDFS
Demo
HDFS数据流
IO流写流程
IO流方式上传文件 (Java)
IO流读流程
IO流方式下载文件 (Java)
副本节点选择
低版本Hadoop
第一个副本在客户端所处的节点上,但是如果客户端是在集群外,随机选取一个节点
第二个副本和第一个副本位于不同机架的随机节点上,也就是不和第一个副本在相同机架。
第三个副本和第二个副本位于相同机架,节点随机
Hadoop2.5版本以上
HDFS误区
小文件存储
每个文件均按照块存储,每个块的元数据存储在NamNode的内存中(一个文件/目录/文件块一般占有150字节的元数据内存空间),因此Hadoop存储小文件会非常低效,因为大量小文件会耗尽NameNode中大部分内存,但存储小文件所需要的磁盘容量和存储这些文件原始内容所需要的磁盘空间相比也不会增多。
例如:上传一个文件1MB,那么这个文件会在HDFS中的一个块存储着,这个块默认是128MB,那么是不是占用了128MB的磁盘空间呢?
副节点处理
HDFS是先把当前这个节点处理完,在去处理副本节点的。
回收站
HDFS全过程
MapReduce
MapReduce是什么?
运算程序,并发的运行在一个Hadoop集群上。
作用
特点
核心思想
分布式的运算程序最少需要分成两个阶段:
第一个阶段:MapTask并发实例,完全并行运行,互不相干
第二个阶段:ReduceTask并发实例,互不相干,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出
MapReduce编程模型只能包含一个Map阶段和Reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序,串行运行。
总结
Map:并行处理任务(运算)。
Reduce:等待相关的所有Map处理完任务,在将任务数据汇总输出。
MRAppMaster:负责整个程序的过程调度和状态协调。
MapReduce进程
MRAppMaster:负责整个程序的过程调度和状态协调。
MapTask:负责Map阶段的整个数据处理流程。
ReduceTask:负责Reduce阶段的整个数据处理流程。
序列化
Java类型 | Hadoop Writable类型 |
boolean | BooleanWritable |
byte | ByteWritable |
int | IntWritable |
float | FloatWritable |
long | LongWritable |
double | DoubleWritable |
string | Text |
map | MapWritable |
array | ArrayWritable |
备注:自定义的反序列类中的write方法和read方法中DataOutput和DataInput这两个类所提供的方法中,对应Java类型String的方法,分别是writeUTF()和readUTF()。
实例(统计单词)
程序流程分析
1、MapReduce程序读取输入目录存放的相应文件。
2、客户端在submit方法执行之前,获取到待处理的数据信息,让后根据急群众参数配置形成一个任务分配规划。
computeSliteSize(Math.max(minSize,Math.max(maxSize,blocksize)))=blocksize=128MB
3、客户端提交job.split、jar包、job.xml等文件给Yarn,Yarn中的resourcemanager启动MRAppMater。
4、MRAppMater启动后根据job的描述信息,计算出需要的MapTask实例数量,然后向集群申请机器,启动相应数量的Map Task进程。
5、MapTask利用客户指定的InputFormat来读取数据,形成KV对。
6、MapTask将输入KV对传递给客户定义的map()方法,做逻辑运算。
7、map()运算完毕后将运算结果的KV对,手机到MapTask缓存。
8、MapTask缓存中的KV对按照K分区排序后不断写到磁盘文件。
9、MRAppMaster监控到所有MapTask进程任务完成后,会根据用户指定的参数启动相应数量的ReduceTask进程,并告知ReduceTask进程要处理的数据分区。
10、ReduceTask进程启动后,根据MRAppMaster告知待处理数据所在位置,从N台MapTask运行所在的机器上获取到N个MapTask输出结果文件,并在本地运行重新归并排序,按照相同Key的KV为一个组,调用客户定义的reduce()方法进行逻辑运算。
11、ReduceTask运算完毕后,调用客户指定的OuputFormat将结果数据输出(文件)到外部存储。
说明:
数据切片
切片流程
切片:
第一块:128MB
源码:computeSliteSize(Math.max(minSize,Math.max(naxSize,blocksize)));
注意:块是HDFS上物理存储的数据,切片只是逻辑上的划分。
FileInputFormat中默认的切片机制
MinSize(切片最小值):如果比块大小还大,则会让切片变得比块还大。
假设:块大小128MB
小文件切片处理
如果有大量的小文件,而每一个文件都是一个单独的切片,都会各自交给一个MapTask处理,那么需要开启大量的MapTask,则会产生大量的MapTask,导致处理效率低下。
解决方案
文件合并
备注:在运行日志中查找number of就可以看到了
Shuffle机制
1、在MapReduce中,Map阶段处理的数据如何传递给Reduce阶段额,是MapReduce框架中关机的一个流程,这个流程就叫Shuffle。
Shuffle机制缓存流程图
MapReduce详细运行流程
总结
分区
自定义分区
总结
reduce数量小于分区数量就会报错。
reduce数量是1,那么则所有结果输出到一个文件内,即便配置了分区也不会去跑分区的代码(执行分区)
reduce数量大于分区数量,输出的其他文件为空
分区数量 = reduce数量,按照分区数量输出结果文件数量
分区就是对map的结果数据进行二次处理,从而再去决定是否影响输出的reduce结果输出。
排序
自定义排序
总结
Shullt规定Key是要进行排序的,如果作为Key是必须要实现WritableComparable接口的。
Combiner合并
ReducrTask是接收总的MapTask结果,Combiner在每一个MapTask运行的,对每每个MapTask的结果汇总(局部汇总),将MapTask汇总后之后进行压缩传输,可以减少网络传输量。
如:
1、在每一个MapTask进行求平均值之后在ReduceTask再求一次平均值,结果是不一样的。
这两种结果是不一样的。
自定义Combiner合并
分组
自定义分组
自定义InputFormat
1、设置文件不可切割
2、读取到整个文件,并且整个文件的数据作为value输出给MapTask(将分片传进去去读取后,将读取到的所有分片数据合并给到MapTask)
3、MapTask在对合并后的数据做操作
自定义OutputFormat
计数器
Hadoop为每一个作业维护了若干个内置计算器,以描述多项指标,例如:某些计数器记录已处理的字节数等。
计数器的使用
说明:计数器的结果在程序运行后的控制台日志中可查看
总结
因为数据可能存储在服务器1或服务器2…服务器,那么不需要移动数据,负责执行任务的服务器,到指定的路径,下载要运算的任务jar包,直接在本地运行,那么当数据非常大的时候就不用去移动数据。
YARN
Yarn是什么?
Yarn机制
Yarn作业流程
1、客户端将MapReduce程序提交到客户端所在的节点。
2、YarnRunner就向RsourceManager申请一个Application。
3、RsourceManager内部运行一下,看看哪个节点离提交申请节点近,以及系统资源等,内部运行完了,就将应用程序资源路径返回给YarnRunner。
4、程序就将运行程序所需要的资源提交到HDFS上。
5、程序资源提交完后,申请运行MRAppMaster。
6、RsourceManager将用户请求转化为一个task(任务),并寻找最适合的NodeManager,并将任务分配给这个NodeManager。
7、NodeManager领取到任务后,创建容器(Container),并产生MRAppMaster。
8、MRAppMaster向RsourceManager申请运行N个MapTask容器(切片文件中有说明)。
9、RsourceManager又寻找了一下,将MapTask分配给另外两个NodeManager,这两个NodeManager领取到任务,并且创建容器(Container)。
10、RsourceManager告知申请运行MapTask容器的NodeManger,向那两个接受到任务的NodeManager发送程序启动脚本,这两个NodeManger就分别启动MapTask,MapTask对数据进行分区排序。
11、MRAppMaster看程序都跑完了,赶紧申请2个容器,运行ReduceTask。
12、ReduceTask的容器向MapTask容器获取相应分区的数据,并执行任务。
13、程序运行完毕后,MapResource会向RsourceManager注销自己。
准备
1、三台机器
2、ssh
3、防火墙
配置
JAVA_HOME
hadoop-env.sh
yarn-env.sh
mapred-env.sh
core-site.xml
<!-- 指定HDFS中NameNode的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop-senior00-levi.com:8082</value>
</property>
<!-- 指定hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-2.5.0-cdh5.3.6/data/tmp</value>
</property>
yarn-site.xml
<!-- Site specific YARN configuration properties -->
<!-- reducer获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 指定YARN的ResourceManager的地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop-senior01-levi.com</value>
</property>
<!-- 任务历史服务 -->
hdfs-site.xml
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop-senior02-levi.com:50090</value>
</property>
<!-- 指定name.dir,默认就是,但是避免未启用,设置一下 -->
<property>
</property>
mapred-site.xml
<!-- 指定mr运行在yarn上 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<!-- 配置 MapReduce JobHistory Server 地址 ,默认端口10020 -->
<property>
</property>
<!-- 配置 MapReduce JobHistory Server web ui 地址, 默认端口19888 -->
<property>
slaves
hadoop-senior00-levi.com
hadoop-senior01-levi.com
hadoop-senior02-levi.com
Hadoop-HA
Hadoop为什么要有HA?
Hadoop-HA是什么?
两个基本问题:
1、第一台服务器和第二台服务器的数据必须要同步。
Hadoop-HA通过edits-log的变化,来将数据写入到JournalNode节点里面去,以分享给其他的NameNode。
2、要解决第一台和第二台服务器同时启用的情况,在这种情况下,子节点怎么提交数据,会提交到两台服务器,但是又会出现抢占资源的情况,(给一个人送东西和给两个人送东西所耗费的体力是不言而喻的),
这个问题在Hadoop-HA中称为脑裂,借助第三方框架(Zookeeper)实现隔离机制来解决脑裂这个问题。