Hadoop进阶

HDFS

hdfs默认文件配置:https://hadoop.apache.org/docs/r3.3.4/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml

各类机制

块 :默认统一大小128m : 为了方便统一管理
在这里插入图片描述

副本: 默认3个的原因: 为了保证数据的安全性
在这里插入图片描述

副本机制: 为了保证数据安全和效率,block块信息存储多个副本,第一副本保存在客户端所在服务器,第二副本保存在和第一副本不同机架服务器上,第三副本保存在和第二副本相同机架不同服务器

负载均衡机制: namenode为了保证不同的datanode中block块信息大体一样,分配存储任务的时候会优先保存在余量比较大的datanaode上

心跳机制: datanode每隔3秒钟向namenode汇报自己的状态信息,如果某个时刻,datanode连续10次不汇报了,namenode会认为datanode有可能宕机了,namenode就会每5分钟(300000毫秒)发送一次确认消息,连续2次没有收到回复,就认定datanode此时一定宕机了(确认datanode宕机总时间3*10+5*2*60=630秒)

写入数据原理

1.客户端发起写入数据的请求给namenode
2.namenode接收到客户端请求,开始校验(是否有权限,路径是否存在,文件是否存在等),如果校验没问题,就告知客户端可以写入
3.客户端收到消息,开始把文件数据分割成默认的128m大小的的block块,并且把block块数据拆分成64kb的packet数据包,放入传输序列

4.客户端携带block块信息再次向namenode发送请求,获取能够存储block块数据的datanode列表
5.namenode查看当前距离上传位置较近且不忙的datanode,放入列表中返回给客户端
6.客户端连接datanode,开始发送packet数据包,第一个datanode接收完后就给客户端ack应答(客户端就可以传入下一个packet数据包),同时第一个datanode开始复制刚才接收到的数据包给node2,node2接收到数据包也复制给node3(复制成功也需要返回ack应答),最终建立了pipeline传输通道以及ack应答通道
7.其他packet数据根据第一个packet数据包经过的传输通道和应答通道,循环传入packet,直到当前block块数据传输完成(存储了block信息的datanode需要把已经存储的块信息定期的同步给namenode)

8.其他block块数据存储,循环执行上述4-7步,直到所有block块传输完成,意味着文件数据被写入成功(namenode把该文件的元数据保存上)
9.最后客户端和namenode互相确认文件数据已经保存完成(也会汇报不能使用的datanode)

注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试

读取数据原理

在这里插入图片描述

1.客户端发送读取文件请求给namenode

2.namdnode接收到请求,然后进行一系列校验(路径是否存在,文件是否存在,是否有权限等),如果没有问题,就告知可以读取
3.客户端需要再次和namenode确认当前文件在哪些datanode中存储
4.namenode查看当前距离下载位置较近且不忙的datanode,放入列表中返回给客户端

5.客户端找到最近的datanode开始读取文件对应的block块信息(每次传输是以64kb的packet数据包),放到内存缓冲区中
6.接着读取其他block块信息,循环上述3-5步,直到所有block块读取完毕(根据块编号拼接成完整数据)
7.最后从内存缓冲区把数据通过流写入到目标文件中

8.最后客户端和namenode互相确认文件数据已经读取完成(也会汇报不能使用的datanode)

注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试

edits和fsimage文件

namenode管理元数据: 基于edits和FSImage的配合,完成整个文件系统文件的管理。每次对HDFS的操作,均被edits文件记录, edits达到大小上限后,开启新的edits记录,定期进行edits的合并操作
    如当前没有fsimage文件,  将全部edits合并为第一个fsimage文件
    如当前已存在fsimage文件,将全部edits和已存在的fsimage进行合并,形成新的fsimage

    edits编辑文件: 记录hdfs每次操作(namenode接收处理的每次客户端请求)
    fsimage镜像文件: 记录某一个时间节点前的当前文件系统全部文件的状态和信息(namenode所管理的文件系统的一个镜像)

SecondaryNameNode辅助合并元数据: SecondaryNameNode会定期从NameNode拉取数据(edits和fsimage)然后合并完成后提供给NameNode使用。
    对于元数据的合并,是一个定时过程,基于两个条件:
    dfs.namenode.checkpoint.period:默认3600(秒)即1小时
    dfs.namenode.checkpoint.txns: 默认1000000,即100W次事务
 
    dfs.namenode.checkpoint.check.period: 检查是否达到上述两个条件,默认60秒检查一次,只要有一个达到条件就执行拉取合并

内存/文件元数据

namenode和secondarynamenode:  配合完成对元数据的保存

元数据: 内存元数据 和 文件元数据 两种分别在内存和磁盘上

内存元数据: namnode运行过程中产生的元数据会先保存在内存中,再保存到文件元数据中。
内存元数据优缺点: 优点: 因为内存处理数据的速度要比磁盘快。  缺点: 内存一断电,数据全部丢失

文件元数据: Edits 编辑日志文件和fsimage 镜像文件
Edits编辑日志文件: 存放的是Hadoop文件系统的所有更改操作(文件创建,删除或修改)的日志,文件系统客户端执行的更改操作首先会被记录到edits文件中
Fsimage镜像文件: 是元数据的一个持久化的检查点,包含Hadoop文件系统中的所有目录和文件元数据信息,但不包含文件块位置的信息。文件块位置信息只存储在内存中,是在 datanode加入集群的时候,namenode询问datanode得到的,并且不间断的更新

fsimage和edits关系: 两个文件都是经过序列化的,只有在NameNode启动的时候才会将fsimage文件中的内容加载到内存中,之后NameNode把增删改查等操作记录同步到edits文件中.使得内存中的元数据和实际的同步,存在内存中的元数据支持客户端的读操作,也是最完整的元数据。

图解

查看历史编辑文件

命令:  hdfs oev -i edits文件名 -o 自定义文件名.xml
[root@node1 current]\# cd /export/data/hadoop/dfs/name/current
[root@node1 current]\# hdfs oev -i edits_0000000000000033404-0000000000000033405 -o 405_edit.xml
[root@node1 current]\# cat 405_edit.xml

查看镜像文件

命令:  hdfs oiv -i fsimage文件名 -p XML -o 自定义文件名.xml
[root@node1 current]\# cd /export/data/hadoop/dfs/name/current
[root@node1 current]\# hdfs oiv -i fsimage_0000000000000033405 -p XML -o 405_fsimage.xml
[root@node1 current]\# cat 405_fsimage.xml

元数据存储的原理

注意: 第一次启动namenode的时候是没有编辑日志文件和镜像文件的,下图主要介绍的是第二次及以后访问的时候情况流程

1.namenode第一次启动的时候先把最新的fsimage文件中内容加载到内存中,同时把edits文件中内容也加载到内存中
2.客户端发起指令(增删改查等操作),namenode接收到客户端指令把每次产生的新的指令操作先放到内存中
3.然后把刚才内存中新的指令操作写入到edits_inprogress文件中
4.edits_inprogress文件中数据到了一定阈值的时候,把文件中历史操作记录写入到序列化的edits备份文件中
5.namenode就在上述2-4步中循环操作...

6.当secondarynamenode检测到自己距离上一次检查点(checkpoint)已经1小时或者事务数达到100w,就触发secondarynamenode询问namenode是否对edits文件和fsimage文件进行合并操作
7.namenode告知可以进行合并
8.secondarynamenode将namenode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行合并(这个过程称checkpoint)
9.secondarynamenode把刚才合并后的fsimage.checkpoint文件拷贝给namenode

10.namenode把拷贝过来的最新的fsimage.checkpoint文件,重命名为fsimage,覆盖原来的文件

注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试

安全模式

安全模式: 不允许HDFS客户端进行任何修改文件的操作,包括上传文件,删除文件等操作。

#查看安全模式状态:
[root@node1 /]\# hdfs dfsadmin -safemode get  
Safe mode is OFF
#开启安全模式:
[root@node1 /]\# hdfs dfsadmin -safemode enter
Safe mode is ON
#退出安全模式:
[root@node1 /]\# hdfs dfsadmin -safemode leave
Safe mode is OFF

归档机制

归档原因: 每个小文件单独存放到hdfs中(占用一个block块),那么hdfs就需要依次存储每个小文件的元数据信息,相对来说浪费资源

归档格式: hadoop archive -archiveName 归档名.har -p 原始文件的目录 归档文件的存储目录

准备工作: HDFS上准备一个目录zaoan,里面存储三个文件 1.txt 2.txt 3.txt …

[root@node1 /]\# hadoop archive -archiveName test.har -p /zaoan  /
...
[root@node1 /]\# hdfs dfs -ls /test1.har
Found 4 items
-rw-r--r--   3 root supergroup          0 2022-12-27 15:56 /test.har/_SUCCESS
-rw-r--r--   3 root supergroup        254 2022-12-27 15:56 /test.har/_index
-rw-r--r--   3 root supergroup         23 2022-12-27 15:56 /test.har/_masterindex
-rw-r--r--   3 root supergroup         47 2022-12-27 15:56 /test.har/part-0
[root@node1 /]\# hdfs dfs -cat /test1.har/part-0
...

归档特性:
Hadoop Archives的URI是:har://scheme-hostname:port/路径/归档名.har
scheme-hostname格式为hdfs-域名:端口
如果没有提供scheme-hostname,它会使用默认的文件系统: har:///路径/归档名.har

[root@node1 /]\# hdfs dfs -ls har:///test.har       
Found 3 items
-rw-r--r--   3 root supergroup         15 2022-12-27 15:55 har:///test.har/1.txt
-rw-r--r--   3 root supergroup         16 2022-12-27 15:55 har:///test.har/2.txt
-rw-r--r--   3 root supergroup         16 2022-12-27 15:55 har:///test.har/3.txt
[root@node1 /]\#  hdfs dfs -cat  har:///test.har/1.txt  
...
[root@node1 /]\#  hdfs dfs -cat  har:///test.har/2.txt  
...
[root@node1 /]\#  hdfs dfs -cat  har:///test.har/3.txt  
...

垃圾桶机制

在虚拟机中rm命令删除文件,默认是永久删除

在虚拟机中需要手动设置才能使用垃圾桶回收: 把删除的内容放到: /user/root/.Trash/Current/
先关闭服务: 在 node1 中执行 stop-all.sh 新版本不关闭服务也没有问题
再修改文件 core-site.xml : 进入/export/server/hadoop-3.3.0/etc/hadoop目录下进行修改

<property>    
	<name>fs.trash.interval</name>
    <value>1440</value> 
</property>  

其中,1440 表示 1440分钟,也就是 24小时,一天的时间。

设置了垃圾桶机制好处: 文件不会立刻消失,可以去垃圾桶里把文件恢复,继续使用

# 没有开启垃圾桶效果
[root@node1 hadoop]\# hdfs dfs -rm /zaoan/hello.txt
Deleted /zaoan/hello.txt

# 开启垃圾桶
[root@node1 ~]\#cd /export/server/hadoop-3.3.0/etc/hadoop
[root@node1 hadoop]\# vim core-site.xml
# 注意: 放到<configuration>内容</configuration>中间
<property>
    <name>fs.trash.interval</name>
    <value>1440</value>
</property>

# 开启垃圾桶效果
[root@node1 hadoop]\# hdfs dfs -rm -r /test1.har
2023-05-24 15:07:33,470 INFO fs.TrashPolicyDefault: Moved: 'hdfs://node1.itcast.cn:8020/test1.har' to trash at: hdfs://node1.itcast.cn:8020/user/root/.Trash/Current/test1.har

# 开启垃圾桶后并没有真正删除,还可以恢复
[root@node1 hadoop]\# hdfs dfs -mv /user/root/.Trash/Current/test1.har  / 

MR

单词统计流程

已知文件内容:  
    hadoop hive hadoop spark hive 
    flink hive linux hive mysql

input结果: 
        k1(行偏移量)   v1(每行文本内容)
        0   		 hadoop hive hadoop spark hive 
        30   		 flink hive linux hive mysql
map结果:
        k2(split切割后的单词)  v2(拼接1)     
        hadoop  			 1
        hive   				 1
        hadoop  			 1
        spark  				 1
        hive   				 1
        flink  				 1
        hive   				 1
        linu  				 1
        hive   				 1
        mysql  				 1
分区/排序/规约/分组结果:
        k2(排序分组后的单词)   v2(每个单词数量的集合)
        flink   		    [1]
        hadoop  			[1,1]
        hive    			[1,1,1,1]
        linux   			[1] 
        mysql   			[1]
        spark   			[1]
reduce结果:
        k3(排序分组后的单词)   v3(聚合后的单词数量)
        flink 				 1
        hadoop 				 2
        hive   				 4
        linux  				 1
        mysql  				 1
        spark  				 1
output结果:   注意: 输出目录一定不要存在,否则报错
        flink   1
        hadoop  2
        hive    4
        linux   1
        mysql   1
        spark   1

MR底层原理

在这里插入图片描述

map阶段

第一阶段是把输入目录下文件按照一定的标准逐个进行逻辑切片,形成切片规划。默认情况下Split size 等于 Block size。每一个切片由一个MapTask处理(当然也可以通过参数单独修改split大小)
第二阶段是对切片中的数据按照一定的规则解析成对。默认规则是把每一行文本内容解析成键值对。key是每一行的起始位置(单位是字节),value是本行的文本内容。(TextInputFormat)
第三阶段是调用Mapper类中的map方法。上阶段中每解析出来的一个,调用一次map方法。每次调用map方法会输出零个或多个键值对
第四阶段是按照一定的规则对第三阶段输出的键值对进行分区。默认是只有一个区。分区的数量就是Reducer任务运行的数量。默认只有一个Reducer任务
第五阶段是对每个分区中的键值对进行排序。首先,按照键进行排序,对于键相同的键值对,按照值进行排序。比如三个键值对<2,2>、<1,3>、<2,1>,键和值分别是整数。那么排序后的结果是<1,3>、<2,1>、<2,2>。
如果有第六阶段,那么进入第六阶段;如果没有,直接输出到文件中
第六阶段是对数据进行局部聚合处理,也就是combiner处理。键相等的键值对会调用一次reduce方法。经过这一阶段,数据量会减少。本阶段默认是没有的。

注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试

shuffle阶段

shuffle是Mapreduce的核心,它分布在Mapreduce的map阶段和reduce阶段。一般把从Map产生输出开始到Reduce取得数据作为输入之前的过程称作shuffle。
Collect阶段:将MapTask的结果输出到默认大小为100M的环形缓冲区,保存的是key/value,Partition分区信息等
Spill阶段:当内存中的数据量达到一定的阀值(80%)的时候,就会将数据写入本地磁盘,在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置了combiner,还会将有相同分区号和key的数据进行排序
Merge阶段:把所有溢出的临时文件进行一次合并操作,以确保一个MapTask最终只产生一个中间数据文件
Copy阶段: ReduceTask启动Fetcher线程到已经完成MapTask的节点上复制一份属于自己的数据,这些数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阀值的时候,就会将数据写到磁盘之上
Merge阶段:在ReduceTask远程复制数据的同时,会在后台开启两个线程对内存到本地的数据文件进行合并操作。
Sort阶段:在对数据进行合并的同时,会进行排序操作,由于MapTask阶段已经对数据进行了局部的排序,ReduceTask只需保证Copy的数据的最终整体有效性即可。 

注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试

reduce阶段

第一阶段是Reducer任务会主动从Mapper任务复制其输出的键值对。Mapper任务可能会有很多,因此Reducer会复制多个Mapper的输出。

第二阶段是把复制到Reducer本地数据,全部进行合并,即把分散的数据合并成一个大的数据。再对合并后的数据排序。

第三阶段是对排序后的键值对调用reduce方法。键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对。最后把这些输出的键值对写入到HDFS文件中。

注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试

YARN

yarn提交mr流程

1.客户端提交一个MR程序给ResourceManager(校验请求是否合法...)

2.如果请求合法,ResourceManager随机选择一个NodeManager用于生成appmaster(应用程序控制者,每个应用程序都单独有一个appmaster)
3.appmaster会主动向ResourceManager的应用管理器(application manager)注册自己,告知自己的状态信息,并且保持心跳
4.appmaster会根据任务情况计算自己所需要的container资源(cpu,内存...),主动向ResourceManager的资源调度器(resource scheduler)申请并获取这些container资源

5.appmaster获取到container资源后,把对应指令和container分发给其他NodeManager,让NodeManager启动task任务(maptask任务,reducetask任务)
6.NodeManager要和appmaster保持心跳,把自己任务计算进度和状态信息等同步给appmaster,(注意当maptask任务完成后会通知appmaster,appmaster接到消息后会通知reducetask去maptask那儿拉取数据)直到最后任务完成

7.appmaster会主动向ResourceManager注销自己(告知ResourceManager可以把自己的资源进行回收了,回收后自己就销毁了)

调度器

调度器的配置在yarn-site.xml查找,如果没有就去yarn-default.xml中找
网址: https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
配置项和默认值如下yarn.resourcemanager.scheduler.class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler

先进先出调度器

FIFO Scheduler: 把应用按提交的顺序排成一个队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。
好处:  能够保证每一个任务都能拿到充足的资源, 对于大任务的运行非常有好处
弊端:  如果先有大任务后有小任务,会导致后续小任务无资源可用, 长期处于等待状态
应用:  测试环境

公平调度器

Fair Scheduler :不需要保留集群的资源,因为它会动态在所有正在运行的作业之间平衡资源 , 当一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当后面有小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。

好处:  保证每个任务都有资源可用, 不会有大量的任务等待在资源分配上
弊端: 如果大任务非常的多, 就会导致每个任务获取资源都非常的有限, 也会导致执行时间会拉长
应用: CDH商业版本的hadoop

容量调度器

Capacity Scheduler: 为每个组织分配专门的队列和一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。在每个队列内部,资源的调度是采用的是先进先出(FIFO)策略。
好处: 可以保证多个任务都可以使用一定的资源, 提升资源的利用率
弊端: 如果遇到非常的大的任务, 此任务不管运行在那个队列中, 都无法使用到集群中所有的资源,  导致大任务执行效率比较低,当任务比较繁忙的时候, 依然会出现等待状态
应用: apache开源版本的hadoop

示例:

调度器的使用是通过yarn-site.xml配置文件中的
yarn.resourcemanager.scheduler.class参数进行配置的,默认采用Capacity Scheduler调度器
下面是一个简单的Capacity调度器的配置文件,文件名为capacity-scheduler.xml>>在这个配置中,在root队列下面定义了两个子队列prod和dev,分别占40%和60%的容量

       <!-- 队列分为两份 prod 和 dev    -->
       <name>yarn.scheduler.capacity.root.queues</name>
       <value>prod,dev</value>    </property>
      <property>
       <!--prod占比 40%-->
       <name>yarn.scheduler.capacity.root.prod.capacity</name>
       <value>40</value>    </property>    <property>
       <!--dev占比 60%-->
       <name>yarn.scheduler.capacity.root.dev.capacity</name>
       <value>60</value>    </property>    <property>
       <!-- dev的最大占比 75%-->
       <name>yarn.scheduler.capacity.root.dev.maximum-capacity</name>
       <value>75</value>    </property> 

prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。
dev的maximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急。

ev,分别占40%和60%的容量

<property>
	<!-- 队列分为两份 prod 和 dev    -->
	<name>yarn.scheduler.capacity.root.queues</name>
	<value>prod,dev</value>
</property>
<property>
	<!--prod占比 40%-->
	<name>yarn.scheduler.capacity.root.prod.capacity</name>
	<value>40</value>
</property>
<property>
	<!--dev占比 60%-->
	<name>yarn.scheduler.capacity.root.dev.capacity</name>
	<value>60</value>
</property>
<property>
	<!-- dev的最大占比 75%-->
	<name>yarn.scheduler.capacity.root.dev.maximum-capacity</name>
	<value>75</value>
</property>

prod由于没有设置maximum-capacity属性,它有可能会占用集群全部资源。
dev的maximum-capacity属性被设置成了75%,所以即使prod队列完全空闲dev也不会占用全部集群资源,也就是说,prod队列仍有25%的可用资源用来应急。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早安Naor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值