admin管理员组文章数量:1579446
系列文章目录
一、Hive调优(面试重点)
二、Hadoop原理(面试重点)
文章目录
- 系列文章目录
- 前言
- 一、Hive调优(熟悉)
- 6、join的优化操作
- 7、列裁剪
- 8、分区裁剪
- 9、group by 操作(Map端聚合)
- 10、count(distinct)
- 11、笛卡尔积
- 12、动态分区
- 13、如何调整map和reduce的数量
- 14、并行执行
- 15、严格模式
- 16、JVM 重用
- 17、推测执行
- 18、执行计划explain
- 19 、Hive调优总结
- 二、Hadoop原理
- 1、HDFS
- 1.1 块和副本
- 1.2 三大机制
- 1.3 写入数据原理[面试]
- 1.4 读取数据原理[面试]
- 1.5 edits和fsimage文件
- 1.6 内存/文件元数据
- 1.6.1 图解
- 1.6.2 查看历史编辑文件
- 1.6.3 查看镜像文件
- 1.7 元数据存储的原理[面试]
- 1.8 安全模式
- 1.9 归档机制
- 1.10 垃圾桶机制
- 2、MapReduce
- 2.1 单词统计流程
- 2.2 MR底层原理[面试]
- 2.2.1 map阶段
- 2.2.2 shuffle阶段
- 2.2.3 reduce阶段
前言
真实大数据开发常问面试题
本文主要论述,工作中常用的Hive调优和面试常考的Hadoop原理。
提示:以下是本篇文章正文内容,下面案例可供参考
一、Hive调优(熟悉)
6、join的优化操作
思考: 在通过hive执行多表查询的SQL, 最终hive翻译的MR,是如何完成join的工作的呢?
默认的join行为, 基于reduce端的join工作
思考, 请问上述join存在哪些问题?
1、导致reduce的压力剧增,所有的数据全部都汇总到reduce中
2、当有了多个reduce之后,如果某个join的字段出现了大量的数据,那么会导致这些大量的数据都分配给到同一个reduce,从而导致数据倾斜
数据倾斜: 实际例子解释,例如有100袋水泥,1袋给别人,99袋给你搬,那么你出现了数据倾斜
那么如何解决reduce端join遇到问题? 可以通过底层map 端 join实现,还可以sql语句join之前提前过滤数据或者转换数据实现
join之前提前过滤数据例子:
1- 没有提前过滤的SQL:
语句: select * from a left join b on a.id = b.id where a.age>=18;
过程: 先将a表和b表的所有数据全部加载出来(全表扫描),然后进行join关联操作,最后对join后的数据进行age>=18的过滤操作。这样会导致最开始处理的数据量比较大
2- 有提前过滤的SQL
语句: select * from (select * from a where age>=18) as new_a left join b on a.id = b.id;
过程: 在对a表数据进行全表扫描的时候同时对数据按照age>=18进行过滤,过滤出来以后再和b表进行join关联。这样能够让后续处理的数据量变少
-
- 大表和小表进行join:
-
解决方案: map join
-
如何开启这种操作呢?
set hive.auto.convert.join = true; -- 默认为true 开启mapJoin支持 set hive.mapjoin.smalltable.filesize= 25000000; 设置 小表的最大的数据量 23.84m
-
在执行SQL, 应该将小表放置前面呢, 还是大表放置在前面呢,还是都可以呢 ?
(hive1旧版本中) : 要求 必须将小表在前大表在后 ,只有这样才可能走Map Join (hive2、3新版中): 无所谓, 谁在前, 谁在后, 没有任何的影响, hive会自动进行优化
-
- 大表和大表join
-
解决方案:
1- 将数据过滤提前,也就是在表join之前就先对数据进行过滤,能够减少后续数据处理的量 2- 如果join字段上,有很多空值(也就是null值),这种情况进行join的时候,容易出现数据倾斜的问题。可以在该字段的后面(一般是放在后面)跟上一些随机值 3- 使用分桶表,但是一般在公司里面很少说为了去优化join将表变成分桶
7、列裁剪
Hive在读数据的时候,可以只读取查询中所需要用到的列,而忽略其他列
例如:
假设有一个表A: a b c d e 5个字段, 请查看以下SQL
select a,b from A where a=xxx;
在这条SQL, 发现没有使用c d e 字段, 在from A表时候, 读取数据, 只需要将a列 和 b列数据读取出来即可, 不需要读取cde列字段, 这样可以减少读取的数据量, 从而提升效率
如何配置呢?
--【列裁剪(只读取sql语句需要的字段,节省读取开销,提升效率)
set hive.optimize.cp=true; -- 默认就是true (在hive 2.x中无需在配置了, 直接为固定值: true)
8、分区裁剪
如果操作的表是一张分区表, 那么建议一定要带上分区字段, 以减少扫描的数据量, 从而提升效率,
如何配置呢?
-- 分区裁剪
set hive.optimize.pruner=true; --默认为就是true (在hive 2.x中无需在配置了, 直接为固定值: true)
-- 优化前
select * from multi_pat_tb where my_date>='2022-05-01' and my_date<='2022-05-02'
-- 优化后
select * from multi_pat_tb where my_date>='2022-05-01' and my_date<='2022-05-02'
and year=2022 and month=5
总结:
列裁剪和分区裁剪都是为了减少后续处理的数据量
9、group by 操作(Map端聚合)
方案一:
(1)是否在Map端进行聚合,默认为True
set hive.map.aggr = true;
(2)在Map端进行聚合操作的条目数目
set hive.groupby.mapaggr.checkinterval = 100000;
方案二: 官方称为 负载均衡
(3)有数据倾斜的时候进行负载均衡(默认是false)
set hive.groupby.skewindata = true;
第一个MR Job中,Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;
第二个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。
10、count(distinct)
说明 : count(distinct) 在数据量比较大的情况下, 效率并不高
思考: 你知道是为什么吗?
因为该操作需要对全局数据进行去重和计数处理
原因如下:
请问1: 执行count操作的时候, hive翻译的MR, reduce数量是否可以有多个? 必然不会有多个, 只能有一个, 因为全局求最终结果
此时如果执行统计的时候, 需要进行去重,那么去重工作是由reduce执行去重操作, 由于reduce只有一个, 所有的数据都在一个reduce中, 此时reduce的压力比较大
希望执行去重工作可能有多个reduce一起来执行操作, 此时可以将SQL优化:
原有:
select count(distinct ip) from ip_tab;
优化:
select
count(ip)
from
(select ip from ip_tab group by ip) tmp;
请注意: 这样的做法, 虽然会运行两个MR, 但是当数据量足够庞大的时候, 此操作绝对是值得的, 如果数据量比较少, 此操作效率更低
-- count(distinct)优化
-- 没有优化前。48s
select count(distinct city_id) from log_text;
-- 优化后。1分22秒
set hive.optimize.countdistinct; -- 默认为true,也就是开启
set hive.optimize.countdistinct=true;
select count(city_id) from (select city_id from log_text group by city_id) as tmp;
注意: 为什么优化后运行时间反而增加了呢?
因为目前数据量太小,体现不出优势。类似雅迪和兰博基尼的启动速度
11、笛卡尔积
什么是笛卡尔积呢? 在进行join的时候, 两个表乘积之后结果就是笛卡尔积的结果
比如: 一个表有5条, 一个表有3条数据, 笛卡尔积结果就有15条数据 , 笛卡尔积中有大量数据都是无用数据
什么时候会产生笛卡尔积呢?
在多表join的时候, 关联条件缺少或者使用错误的关联条件以及将关联条件放置在where中都会导致笛卡尔积
在实际使用中, 建议:
1- 在join的时候一定要加上on条件。如果没有可关联的字段,可以写 on 1=1
2- 关联条件要放在on语句里面。不要放在where语句中,因为这种写法会产生笛卡尔积
3- (从业务/需求层面)如果在实际开发中真的发现没有可关联的字段/条件,可以和业务方进行沟通,是否要调整需求,或者条数
示例:
-- 笛卡尔积
-- 关联条件放在on语句中,不会产生笛卡尔积
select * from (select * from log_text where city_id=156) as new_a left outer join log_text b on new_a.city_id=b.city_id;
-- 关联条件放在where语句中,会产生笛卡尔积
select * from (select * from log_text where city_id=156) as new_a left outer join log_text b where new_a.city_id=b.city_id;
12、动态分区
需求: 请将下面的一个分区表数据, 拷贝到另一个分区表, 保证对应区数据放置到另一个表的对应区下
如何配置呢?
作用: 帮助一次性灌入多个分区的数据
参数:
set hive.exec.dynamic.partition.mode=nonstrict; -- 开启非严格模式 默认为 strict(严格模式)
set hive.exec.dynamic.partition=true; -- 开启动态分区支持, 默认就是true
可选的参数:
set hive.exec.max.dynamic.partitions=1000; -- 在所有执行MR的节点上,最大一共可以创建多少个动态分区。
set hive.exec.max.dynamic.partitions.pernode=100; -- 每个执行MR的节点上,最大可以创建多少个动态分区
set hive.exec.max.created.files=100000; -- 整个MR Job中,最大可以创建多少个HDFS文件
示例:
-- 动态分区
-- 创建分区表
create table score_part_tb(
name string,
subject string,
score int
) partitioned by (year string)
row format delimited fields terminated by '\t';
-- load导入数据
load data inpath '/dir/score.txt' into table score_part_tb partition (year="2022");
-- 数据验证
select * from score_part_tb;
-- 动态分区参数设置
set hive.exec.dynamic.partition.mode=nonstrict; -- 开启非严格模式 默认为 strict(严格模式)
set hive.exec.dynamic.partition=true; -- 开启动态分区支持, 默认就是true
-- 创建表
create table score_part_tb_dynamic(
name string,
subject string,
score int
) partitioned by (dynamic_year string)
row format delimited fields terminated by '\t';
-- 验证表结构
show create table score_part_tb_dynamic;
select * from score_part_tb_dynamic;
-- 动态分区插入数据中,注意partition后面小括号中指定的是前面表的分区字段
insert into score_part_tb_dynamic partition (dynamic_year) select * from score_part_tb;
13、如何调整map和reduce的数量
1>是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。2>是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。3>是不是reduce数越多越好?
答案是否定的。如果reduce设置的过大,对整个作业会产生一定的影响。
①过多的启动和初始化reduce也会消耗时间和资源;
②另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;4>在什么情况下, 只能有一个reduce呢?
以下几种, 不管如何设置, 最终翻译后reduce只能有一个
1) 执行order by操作
2) 执行不需要group by直接聚合的操作
3) 执行笛卡尔积
-
如何调整mapTask数量:
小文件场景:当input的文件都很小,把小文件进行合并归档,减少map数, 设置map数量:
-- 每个Map最大输入大小(这个值决定了合并后文件的数量) set mapred.max.split.size=256000000; -- 一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并) set mapred.min.split.size.per.node=1; -- 一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并) set mapred.min.split.size.per.rack=1; -- 执行Map前进行小文件合并默认CombineHiveInputFormat set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
大文件场景:当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
举例:如果表a只有一个文件,大小为120M,但包含几千万的记录,如果用1个map去完成这个任务,肯定是比较耗时的,
这种情况下,我们要考虑将这一个文件合理的拆分成多个,这样就可以用多个map任务去完成。
set mapred.reduce.tasks=10;
create table a_1 as select * from tab_info distribute by rand(123);
这样会将a表的记录,随机的分散到包含10个文件的a_1表中,再用a_1代替上面sql中的a表,则会用10个map任务去完成。 -
如何reduce的数量:
-- 查看reduces数量 -- 该值默认为-1,由hive自己根据任务情况进行判断。 set mapred.reduce.tasks; set mapreduce.job.reduces; -- (1)每个Reduce处理的数据量默认是256MB左右 set hive.exec.reducers.bytes.per.reducer=256000000; -- (2)每个任务最大的reduce数,默认为1009; set hive.exec.reducers.max=1009; 注意: 以下几种, 不管如何设置, 最终翻译后reduce只能有一个 1) 执行order by操作 2) 执行不需要group by直接聚合的操作 3) 执行笛卡尔积
14、并行执行
在执行一个SQL语句的时候, SQL会被翻译为MR, 一个SQL有可能被翻译成多个MR, 那么在多个MR之间, 有些MR之间可能不存在任何的关联, 此时可以设置让这些没有关联的MR 并行执行, 从而提升效率 , 默认是 一个一个来
如何配置:
set hive.exec.parallel=false; -- 打开任务并行执行,默认关闭
set hive.exec.parallel.thread.number=8; -- 同一个sql允许最大并行度,默认为8。
前提: 服务器必须有资源, 如果没有 即使支持并行, 也没有任何作用
案例:
下面这些SQL案例,都是会翻译成多个MapReduce
select * from A ....
union all
select * from B ...;
例如:
select from (select * from A group by ...) tmp1 join (select * from B group by xxx) on ...
没有开启并行执行的时候,SQL语句间是串行(一个一个来,排了一个对)执行:
15、严格模式
hive提供一种严格模式, 主要目的, 是为了限制一些 效率极低的SQL 防止其执行时间过长, 影响其他的操作
屏蔽一下操作:
1) 执行order by 不加 limit
2) 出现笛卡尔积的现象SQL
3) 查询分区表, 不带分区字段
前提: 数据量足够大, 如果数据量比较少, 严格模式对此三项内容不生效
如何配置:
set hive.mapred.mode = strict; --开启严格模式
set hive.mapred.mode = nostrict; --开启非严格模式 最新默认
注意:
1- 从Hive3.x版本开始,该参数已经失效,内部就是严格模式
2- 前提: 表数据量足够大才会进行严格模式的检查。如果数据量比较少, 严格模式对此三项内容不生效
16、JVM 重用
此操作, 在hive2.x已经不需要配置了, 默认支持
jvm重用: 默认情况下, container资源容器 只能使用一次,不能重复使用, 开启JVM重用, 运行container容器可以被重复使用,在hive2.x已经默认支持了
17、推测执行
调优举例:
大数据小组,假设张三有离职苗头,大数据主管会将张三负责的项目和功能分配给到其他同事来负责。
Hadoop采用了推测执行(Speculative Execution)机制,它根据一定的法则推测出“拖后腿”的任务,并为这样的任务启动一个备份任务,让该任务与原始任务同时处理同一份数据,并最终选用最先成功运行完成任务的计算结果作为最终结果。
hadoop中默认两个阶段(map和reduce)都开启了推测执行机制。
hive本身也提供了配置项来控制reduce-side的推测执行:
set hive.mapred.reduce.tasks.speculative.execution=true;
关于调优推测执行机制,还很难给一个具体的建议。如果用户对于运行时的偏差非常敏感的话,那么可以将这些功能关闭掉。如果用户因为输入数据量很大而需要执行长时间的map或者Reduce task的话,那么启动推测执行造成的浪费是非常巨大。
什么时候需要开启?
如果提交的SQL语句,运行的耗时的远超你的预期。你就可以开启推测执行
什么时候不需要开启?
如果对SQL的运行耗时没有特别严格的要求,那么可以不开启。不开启同时能够节约Yarn集群资源。
18、执行计划explain
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道Hive是如何处理你的SQL语句的。帮助我们了解底层原理,hive调优,排查数据倾斜等有很有帮助
使用示例:explain [...] sql查询语句;
explain sql语句: 查看执行计划的基本信息
(1)stage dependencies:各个stage之间的依赖性
包含多个stage阶段,例如 Stage-1和Stage-0,Stage-1 是根stage,Stage-0 依赖 Stage-1,
(2)stage plan:各个stage的执行计划
包含两部分: map端执行计划树和reduce端执行计划树
explain select * from score_part_tb_dynamic order by score desc;
19 、Hive调优总结
1- 在实际工作中一般不需要针对所有参数去做调整。因为Hive官方已经是提供性能很好的参数配置
2- 理解这些调优手段带来的好处。能够在面试的时候回答出来4-5条具体的调优方式即可,不需要去记忆配置参数
3- 参数调优也不是说一下子就能调的很好,需要反复多次的进行参数调整测试
二、Hadoop原理
1、HDFS
hdfs默认文件配置:https://hadoop.apache/docs/r3.3.4/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
1.1 块和副本
为什么需要将大文件分成不同的block分散到多台服务器上进行存储?因为有如下的优点
1- 避免单台服务器存储空间不够的情况
2- 能够同时利用多台服务器的性能,例如:磁盘读写速度等
block块: HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件拆分成一系列的数据块进行存储,这个数据块被称为block,除了最后一个,所有的数据块都是同样大小的。
block 块大小默认: 128M(134217728字节) 注意: 块同样大小方便统一管理
注意: 为了容错,文件的所有block都会有副本。每个文件的数据块大小和副本系数都是可配置的。
副本系数默认: 3个 副本好处: 副本为了保证数据安全(用消耗存储资源方式保证安全,导致了大数据瓶颈是数据存储)
hdfs默认文件配置:https://hadoop.apache/docs/r3.3.4/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml
如何修改块大小和副本数量呢?可以在hdfs-site.xml中配置如下属性:
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
<description>设置HDFS块大小,单位是b</description>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
图解:
块 :默认统一大小128m : 为了方便统一管理
副本: 默认3个的原因: 为了保证数据的安全性
1.2 三大机制
副本机制: 为了保证数据安全和效率,block块信息存储多个副本,第一副本保存在客户端所在服务器,第二副本保存在和第一副本不同机架服务器上,第三副本保存在和第二副本相同机架不同服务器
负载均衡机制: namenode为了保证不同的datanode中block块信息大体一样,分配存储任务的时候会优先保存在距离近且余量比较大的datanaode上
心跳机制: datanode每隔3秒钟向namenode汇报自己的状态信息,如果某个时刻,datanode连续10次不汇报了,namenode会认为datanode有可能宕机了,namenode就会每5分钟(300000毫秒)发送一次确认消息,连续2次没有收到回复,就认定datanode此时一定宕机了(确认datanode宕机总时间3*10+5*2*60=630秒)。观察地址http://node3:9864/datanode.html
1.3 写入数据原理[面试]
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.4 读取数据原理[面试]
1.客户端发送读取文件请求给namenode
2.namdnode接收到请求,然后进行一系列校验(路径是否存在,文件是否存在,是否有权限等),如果没有问题,就告知可以读取
3.客户端需要再次和namenode确认当前文件在哪些datanode中存储
4.namenode查看当前距离下载位置较近且不忙的datanode,放入列表中返回给客户端
5.客户端找到最近的datanode开始读取文件对应的block块信息(每次传输是以64kb的packet数据包),放到内存缓冲区中
6.接着读取其他block块信息,循环上述3-5步,直到所有block块读取完毕(根据块编号拼接成完整数据)
7.最后从内存缓冲区把数据通过流写入到目标文件中
8.最后客户端和namenode互相确认文件数据已经读取完成(也会汇报不能使用的datanode)
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
1.5 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秒检查一次,只要有一个达到条件就执行拉取合并
1.6 内存/文件元数据
namenode和secondarynamenode: 配合完成对元数据的保存
元数据: 内存元数据 和 文件元数据 两种分别在内存和磁盘上
内存元数据: namnode运行过程中产生的元数据会先保存在内存中,再保存到文件元数据中。
内存元数据优缺点: 优点: 因为内存处理数据的速度要比磁盘快。 缺点: 内存一断电,数据全部丢失
文件元数据: Edits 编辑日志文件和fsimage 镜像文件
Edits编辑日志文件: 存放的是Hadoop文件系统的所有更改操作(文件创建,删除或修改)的日志,文件系统客户端执行的更改操作首先会被记录到edits文件中
Fsimage镜像文件: 是元数据的一个持久化的检查点,包含Hadoop文件系统中的所有目录和文件元数据信息,但不包含文件块位置的信息。文件块位置信息只存储在内存中,是在 datanode加入集群的时候,namenode询问datanode得到的,并且不间断的更新
fsimage和edits关系: 两个文件都是经过序列化的,只有在NameNode启动的时候才会将fsimage文件中的内容加载到内存中,之后NameNode把增删改查等操作记录同步到edits文件中.使得内存中的元数据和实际的同步,存在内存中的元数据支持客户端的读操作,也是最完整的元数据。
1.6.1 图解
edits和fsimage文件所在的位置:namenode运行所在机器的/export/data/hadoop/dfs/name/current
secondaryNameNode对应的目录:/export/data/hadoop/dfs/namesecondary/current
注意:千万不要随便去修改/删除这些文件
1.6.2 查看历史编辑文件
命令: hdfs oev -i edits文件名 -o 自定义文件名.xml
[root@node1 current]# cd /export/data/hadoop/dfs/name/current
[root@node1 current]# hdfs oev -i edits_0000000000000039578-0000000000000039647 -o /home/39647.xml
[root@node1 current]# cat /home/39647.xml
1.6.3 查看镜像文件
命令: 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 /home/405_fsimage.xml
[root@node1 current]# cat /home/405_fsimage.xml
1.7 元数据存储的原理[面试]
注意: 第一次启动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,覆盖原来的文件
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
1.8 安全模式
安全模式: 是namenode的自我保护。不允许HDFS客户端进行任何修改文件的操作,包括上传文件,删除文件等操作。
…
1.9 归档机制
归档原因: 每个小文件单独存放到hdfs中(占用一个block块),那么hdfs就需要依次存储每个小文件的元数据信息,相对来说浪费资源。和压缩文件一样,也就是将多个小文件压缩到一起。小文件了个数过多,会导致map程序过多,这样会占用过多的Yarn集群资源
归档格式: hadoop archive -archiveName 归档名.har -p 原始文件的目录 归档文件的存储目录
准备工作: HDFS上准备一个目录binzi,里面存储三个文件 1.txt 2.txt 3.txt …
[root@node1 /]# hadoop archive -archiveName dir.har -p /dir /
归档特性:
Hadoop Archives的URI是:har://scheme-hostname:port/路径/归档名.har
scheme-hostname格式为hdfs-域名:端口
如果没有提供scheme-hostname,它会使用默认的文件系统: har:///路径/归档名.har
[root@node1 home]# hdfs dfs -cat /dir.har/part-0
512 霸王防脱 20 200
513 蓝月亮洗衣液 10 15
514 心心相印抽纸 18 10
515 雕牌洗洁精 8 104151 耳机 40 1
4152 霸王防脱 28 1
4153 衣架 12 1
511 飘柔洗发水 15 2
512 霸王防脱 20 1
513 蓝月亮洗衣液 10 1
514 心心相印抽纸 18 1521 牙刷套装 15 2
522 小米手机壳 20 1
[root@node1 home]# hdfs dfs -cat har:///dir.har/part-0
cat: `har:///dir.har/part-0': No such file or directory
[root@node1 home]# hdfs dfs -cat har:///dir.har/*
512 霸王防脱 20 200
513 蓝月亮洗衣液 10 15
514 心心相印抽纸 18 10
515 雕牌洗洁精 8 104151 耳机 40 1
4152 霸王防脱 28 1
4153 衣架 12 1
511 飘柔洗发水 15 2
512 霸王防脱 20 1
513 蓝月亮洗衣液 10 1
514 心心相印抽纸 18 1521 牙刷套装 15 2
522 小米手机壳 20 1
您在 /var/spool/mail/root 中有新邮件
[root@node1 home]#
1.10 垃圾桶机制
在虚拟机中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 /binzi/hello.txt
Deleted /binzi/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:8020/test1.har' to trash at: hdfs://node1.itcast:8020/user/root/.Trash/Current/test1.har
# 开启垃圾桶后并没有真正删除,还可以恢复
[root@node1 hadoop]# hdfs dfs -mv /user/root/.Trash/Current/test1.har /
2、MapReduce
2.1 单词统计流程
已知文件内容:
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
2.2 MR底层原理[面试]
2.2.1 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方法。经过这一阶段,数据量会减少。本阶段默认是没有的。
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
2.2.2 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的数据的最终整体有效性即可。
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
2.2.3 reduce阶段
第一阶段是Reducer任务会主动从Mapper任务复制其输出的键值对。Mapper任务可能会有很多,因此Reducer会复制多个Mapper的输出。
第二阶段是把复制到Reducer本地数据,全部进行合并,即把分散的数据合并成一个大的数据。再对合并后的数据排序。
第三阶段是对排序后的键值对调用reduce方法。键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对。最后把这些输出的键值对写入到HDFS文件中。
注意: 不要死记硬背,要结合自己的理解,转换为自己的话术,用于面试
版权声明:本文标题:hive调优:案例详解(第16天) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1727854484a1133876.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论