大数据Hadoop面试题整理

2018.10.22
1.抽象类与接口的区别?
1.语法层面上的区别
  1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
  2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
  3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
  4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2.设计层面上的区别
  1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。例如将鸟,飞机各定义为一个类,将飞行定义为一个接口。
  2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。
  
2.构造方法的定义规则
定义时候的基本构成
修饰词 方法名(参数列表){
   方法体
}
注意点:1.没有返回值这一项 2.方法名必须与类名保持一致 3.不能被static、final、synchronized、abstract和native修饰。

3.List接口与Set接口的区别以及常用子类。
List中的元素,有序(元素的顺序与添加元素的顺序一致)、可重复、可为空;
Set中的元素,无序、不重复、只有一个空元素;
Map中的元素,无序、键不重,值可重、可一个空键、多可空值。
List常用子类ArrayList、Vector、LinkedList,其中ArrayList、Vector底层为数组,查询速度快,插入删除速度慢,LinkedList底层为双向链表,查询速度慢,插入删除速度快。Vector线程安全。
Set常用子类HashSet与TreeSet,其中HashSet底层是哈希表;TreeSet底层是二叉树。
Map常用子类HashMap与TreeMap。


2018.10.23
HDFS 和YARN 的基本概念。
1 HDFS
分布式文件系统,主/从架构
NameNode 负责管理元数据(文件名称,副本数量,文件位置,块大小)。HDFS 存储是以块存储 默认块大小 128MB,hadoop1 中默认的块大小是64MB。一个节点。
DataNode:主要存储真正的数据,多节点。
secondaryNamenode 辅助节点,用于合并两类文件。
Fsimage ,edits 作为元数据的镜像和操作的日志记录。
在HDFS第一次使用的时候需要对其进行格式化,目的是生成fsimage 和 edits 文件。
在这里插入图片描述

2 YARN 资源管理器,操作系统 可以在YARN进行任务的运行,YARN为这些运行的任务分配资源,管理。
主节点: resourceManager 负责全部集群中的资源管理,和任务分配
从节点: nodeManager 负责每个机器上的资源管理


2018.10.23
hadoop常用配置文件位置及其含义。


2018.10.24
1.HDFS的副本复制策略
hadoop官网描述如下:

对于常见情况,当复制因子为3时,HDFS的放置策略是在编写器位于datanode上时将一个副本放在本地计算机上,否则放在随机datanode上,另一个副本放在另一个(远程)机架上的节点上,最后一个在同一个远程机架的不同节点上。此策略可以减少机架间写入流量,从而提高写入性能。机架故障的可能性远小于节点故障的可能性; 此策略不会影响数据可靠性和可用性保证。但是,它确实减少了读取数据时使用的聚合网络带宽,因为块只放在两个唯一的机架而不是三个。使用此策略时,文件的副本不会均匀分布在机架上。三分之一的副本位于一个节点上,三分之二的副本位于一个机架上,另外三分之一均匀分布在剩余的机架上。此策略可提高写入性能,而不会影响数据可靠性或读取性能。

如果复制因子大于3,则随机确定第4个及以下副本的放置,同时保持每个机架的副本数量低于上限(基本上是(副本-1)/机架+ 2)。

由于NameNode不允许DataNode具有同一块的多个副本,因此创建的最大副本数是此时DataNode的总数。

在将存储类型和存储策略的支持添加到HDFS之后,除了上述机架感知之外,NameNode还会考虑策略以进行副本放置。NameNode首先根据机架感知选择节点,然后检查候选节点是否具有与文件关联的策略所需的存储。如果候选节点没有存储类型,则NameNode将查找另一个节点。如果在第一个路径中找不到足够的节点来放置副本,则NameNode会在第二个路径中查找具有回退存储类型的节点。

此处描述的当前默认副本放置策略是正在进行的工作。

概括为:
在这里插入图片描述

2.HDFS写数据流程,画图加文字描述。
在这里插入图片描述
1.客户端向namenode请求上传文件,namenode检测该文件是否已存在,父目录是否存在,然后返回是否可以上传。
2.客户端请求上传第一个block,namenode返回三个节点(dn1,dn2,dn3)。
3.客户端向dn1请求上传数据,dn1收到请求后会调用dn2,dn2调用dn3,建立传输通道,dn1、dn2、dn3逐级应答。
4.客户端开始往dn1上传第一个block(先从磁盘读取放到一个本地内存缓存),以packet为单位。dn1收到一个block就会传给dn2,dn2传给dn3。dn1每传完一个packet会被放入一个应答队列等待应答。
5.当一个block传输完成之后,客户端再次向namenode请求上传第二、第三个block,重复上面的步骤(2-4步),直至文件上传完成。

HDFS读数据流程
在这里插入图片描述
文字描述:
1 客户端通过向namenode请求下载文件 ,namenode 收到请求之后查询元数据信息,找到datanode数据块的信息。
2 客户端挑选一台就近的datanode,进行请求数据。
3 datanode开始传输数据给客户端,是以packet 为单位进行读取。
4 客户端 接收packet 数据,先在本地缓存,最后写入到目标文件。

3.NameNode与DataNode的工作机制。
NameNode工作机制
1.第一次启动:第一次启动都需要格式化nameNode ,创建fsimage,edits. 第一次启动只需要加载fsiamge。
2.如果不是第一次启动: 直接加载edits ,fsimage镜像文件 ,合并成一个新的fsimage 文件,再创建edits 文件记录新的操作行为。
启动的过程中,会存在30秒钟等待时间 ,这个等待的时间就是安全模式。

DataNode工作机制
在这里插入图片描述
文字描述:
1.一个数据块在datanode上是以文件形式存储在磁盘上的,包括了两个文件,一个数据本身,一个是元数据包 包括数据块的长度,,数据块的校验和,由于HDFS上的数据是不允许被重复上传的所以在上传之前会对上传的数据进行检查 ,时间戳。
2.DataNode启动后会向nameNode进行注册,通过后,会周期性的向namenode上报自己的datanode上的块信息。
3.心跳报告,每3秒钟向nameNode进行汇报,心跳的返回结果中带有NameNode 带给该datanode复制数据块,移动数据块的命令, 如果说超过了10分钟datanode没有响应 ,则就会认为这个datanode节点不可用,会选择其他的机器。


2018.10.26
如果NameNode意外终止,secondaryNameNode的工作是什么?它是如何工作的?
secondaryNameNode
1.并非NameNode的热备;
2.辅助NameNode,分担其工作量;
3.定期合并fsimage和edits,推送给NameNode;
4.在紧急情况下,可辅助恢复NameNode。


2018.10.28
HDFS安全模式
在系统的正常操作期间,namenode会在内存中保留所有块位置的映射信息。在安全模式下,各个datanode会向namenode发送最新的块列表信息,namenode了解到足够多的块位置信息之后,即可高效运行文件系统。
如果满足“最小副本条件”,namenode会在30秒钟之后就退出安全模式。所谓的最小副本条件指的是在整个文件系统中99.9%的块满足最小副本级别(默认值:dfs.replication.min=1)。在启动一个刚刚格式化的HDFS集群时,因为系统中还没有任何块,所以namenode不会进入安全模式。


2018.10.30
Writable序列化(Hadoop序列化)与java序列化的区别
1.java序列化的时候会保存类的相关和依赖关系等类的基本信息,但是hadoop序列化的时候不会保存类的信息只会保存字段值。
2.java反序列化相当于每次重新创建一个对象,而Hadoop反序列化的时候是重用对象的,会降低创建对象的资源消耗。
3.Hadoop序列化中定制序列化格式很容易,java比较困难。
4.Hadoop序列化后的数据量小,java序列化后的数据量大。
5.序列化/反序列化方式不同。


MapReduce工作流程(shuffle流程)
在这里插入图片描述


2018.11.05
job在yarn上提交流程
在这里插入图片描述


2018.11.07
zookeeper选举(投票)机制
1.没有数据
通过myid给自己投票,根据myid的大小决定票数(比如myid为1,就给自己投1票),谁的票数多,谁就是leader,其余的为follower。半数以上的节点运行成功之后,才提供服务。
2.有数据
根据xid数据的更新版本号为标准,xid最大的为leader(因为follower要同步leader上的数据,所以要确保leader的数据为最新版本),如果xid一样则判断myid的票数。

HA 高可用原理
在这里插入图片描述
在这里插入图片描述
所谓HA(high available),即高可用(7*24小时不中断服务)。实现高可用最关键的策略是消除单点故障。
Active standby 解决了namenode 单点故障。
存在的服务 : zookeeper(解决一致性问题) ; journalnode(解决edits同步问题); zkfc(解决切换问题,负责监测)。
同步: 元数据(edits ,fsimage ), journalnode 节点,同步edits 编辑日志 。集群中安全性得到了保证,但是一致性却减弱了,为了解决一致性的问题,必须存在zookeeper 。
切换机制: 首先要监控到 namenode 挂了,才能进行切换。如何知道挂掉了: 通过ZKFC RPC 调用监控namenode ,一旦namenode挂掉了,zookeeper 就会通知另外一个namenode 的zkfc 进程启动 standby切换为active,在切换之前会先杀掉之前的active(通过执行一个ssh远程调用)。


2018.11.12
hive的4种排序方式
1.order by全局排序。全部数据划分到一个reduce上。与sql中的order by类似,不同的是,hive中的order by在严格模式下,必须跟limit。

2.sort by 每个mapreduce内部排序。

3.distributed by分区排序,与sql中的group by类似,常与sort by组合使用,distributed by控制map的输出在reduce中如何划分,sort by控制reduce中的数据如何排序。hive要求distributed by语句出现在sort by语句之前。

4.cluster by,当distributed by与sort by字段相同,可以用cluster by代替该组合,但cluster by 不能跟desc,asc。补充:可以这样书写select a.* from (select * from test cluster by id ) a order by a.id ;


2018.11.13
hive调优方式
1.Fetch抓取:把不需要MR任务计算的查询语句设置成不执行MR任务。三个参数,none表示禁用Fetch,所有查询都执行MR任务;more在进行select/filter/limit查询时不会运行MR任务;minimal在select/limit的时候不会运行MR任务,但是filter会运行MR任务。
hive.fetch.task.conversion

2.本地模式:让输入的数据量特别小的任务直接在本地节点上进行处理,而不提交到集群。本地模式通过判断文件的大小(默认128MB)和已输入文件的个数(默认4个)来判断是否在本地执行。
set hive.exec.mode.local.auto=true; //开启本地 mr
set hive.exec.mode.local.auto.inputbytes.max=50000000;
set hive.exec.mode.local.auto.input.files.max=10;

3.表的优化:优化手段有join、行列过滤、分区、分桶、动态分区等等。

4.避免数据倾斜:通过合理设置map和reduce数、小文件合并等方式尽量保证负载均衡。或为了避免因为map或reduce任务卡死导致数据倾斜,通常也设置推测执行。

5.推测执行:为了避免因为程序的BUG/负载不均衡/资源分布不均等原因导致同一作业中某一任务运行速度过慢,设置推测执行,为该任务启动一个备份任务,同时执行,最先运行完成的计算结果作为最终结果。分为map端和reduce端的推测执行。
set mapreduce.map.speculative=true
set mapreduce.reduce.speculative=true

6.并行执行:把没有依赖关系的MR任务设置为并行执行,提高多任务运行时的效率。
set hive.exec.parallel=true ; // 开启任务并行执行
set hive.exec.parallel.thread.number=8; //默认值为8个任务可以同时运行

7.严格模式:为了防止一些不正常的查询语句的执行。
hive.mapred.mode= strict

8.JVM重用:当有很多小文件的时候,每次运行MR任务都会开启一个JVM进程,JVM频繁的开启关闭消耗大量的性能,所以在处理小文件的时候,可以设置JVM重用,让一个JVM处理多个任务后再关闭。
mapreduce.job.jvm.numtasks

9.压缩:通过压缩对项目进行优化。例如开启 map 输出阶段压缩可以减少 job 中 map 和 Reduce task 间数据传输量。

10.执行计划:Hive中提供的可以查看Hql语句的执行计划,在执行计划中会生成抽象语法树,在语法树中会显示HQL语句之间的依赖关系以及执行过程。通过这些执行的过程和依赖可以对HQL语句进行优化。


2018.11.16
final、finally、finalize的区别
final
可以用来修饰类,方法和变量(成员变量或局部变量)。
用final修饰类:表明该类不能被其他类所继承。final类中所有的成员方法都会隐式的定义为final方法。
用final修饰方法:1.把方法锁定,以防止继承类对其进行更改。2.提高效率,在早期的java版本中,会将final方法转为内嵌调用。不过现在已经弃用。
final修饰变量:final成员变量表示常量,只能被赋值一次,赋值后其值不再改变。
finally
异常处理时“善后”的代码:用于资源的释放,比如多线程中锁对象,流的释放,数据库的关闭等。
一般情况下finally都会执行。但特殊情况也可能不会执行:比如try没有执行,或在finally之前执行system.exit(0)终止了java虚拟机的运行,或者在try-catch时线程中断。
finalize
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。
gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
使用finalize还需要注意一个事,调用super.finalize();一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。


Hbase中的rowkey以及热点问题
hbase热点现象:
检索hbase的记录首先要通过rowkey来定义数据行,当大量的client访问hbase集群的一个或少数几个节点,造成少数region server的读/写请求过多,负载过大,最终导致单个主机负载过大,引来性能下降甚至region不可用。
热点产生原因:
有大量连续编号的rowkey,导致大量记录集中在个别region。
避免热点方法:
1.加盐:在rowkey的前面增加随机数。此方式适用于将hbase作为海量存储数据而不频繁查询的业务场景。
2.哈希:Hash散列,将数据打乱。
3.反转:包括rowkey字段反转和时间戳反转。例如联通就是这样。时间戳加手机号20181123_13191***,引入一张索引表存储以上字段,hbase中的rowkey则是以上字段的反转。
rowkey设计原则:
1.rowkey唯一原则
2.rowkey长度原则:
二进制数,可以是任意字符,最多给到64kb,建议10-100个字节,但是越短越好,最好不要超过16个字节。
原因:
1)数据都是存在Hfile中按照key-value进行存储的,如果rowkey超过了100个字节,1000万条数据,100*1000万=10亿个字节,约为1G,极大浪费Hfile的存储资源。
2)memstore将缓存部分数据到内存,如果rowkey过大,内存的有效利用率就会降低,从而降低检索效率。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章