博主今年在准备大数据工程师岗位的校招,整理了大数据相关的部分知识点,希望可以帮助和博主一样备战秋招大数据岗位的朋友,另外,博主正在准备 各大厂已经出来的面试题Q&A的整理,会在这两个星期内发出来,感兴趣的同学可以关注我哦~
如果这篇博文在你面试的时候有帮助的话,欢迎回来还愿哦~
目录
写在前面
java
Hadoop
hdfs
Yarn
hive
zookeeper
flume
sqoop
HBase
1.请说明一下JAVA反射的实现过程和作用分别是什么?
答:实现过程:
java语言编译之后会生成一个字节码文件,反射就是通过字节码文件找到某一个类、类中的方法以及属性等。反射的实现主要借助以下四个类:Class:类对象,Constructor:类的构造器,Field:类中的属性对象,Method:类中的方法对象
作用:
反射机制指的是程序在运行时能够获取自身的信息。只要给定类的名字,那么就可以通过反射机制来获取类的所有信息
2.请简单描述一下JVM加载class文件的原理是什么
答:
JVM中类的装载是由ClassLoader和它的子类来实现的,ClassLoader是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件。
Java中的所有类,都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中。在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的,除非我们有特殊的用法,像是反射,就需要显示的加载所需要的类。类装载方式,有两种:
隐式装载:
程序在运行过程中当碰到通过new等方式生成对象时,隐式调用类装载器加载对应的类到JVM中
显式装载
通过class.forname()等方法,显示加载需要的类,隐式加载与显式加载的本质是一样的。
java的加载是动态的,它并不会一次性将所有类全部加载后再运行,而是保证程序运行的基础类(像是基类)完全加载到JVM中,至于其他类,则在需要的时候才加载,这是为了节省内存。
3.请列举一下,在JAVA虚拟机中,哪些对象可作为ROOT对象
答:
虚拟机中的引用对象
方法区中类静态属性引用的对象
方法区中常量引用对象
本地方法栈中JNI引用对象
4.GC如何判断对象是否需要被回收
答:
即使在可达性分析算法中不可达的对象,也并非是“非回收不可”的,这时候他们暂时处于“等待”阶段,要真正宣告一个对象回收,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与GC ROOTs相连接的引用链,那么它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。(即意味着直接回收)
如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer()线程去执行它,这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样做的原因是,如果一个对象在finalize()方法中执行缓慢,或者发生了死循环(更极端的情况),将很可能会导致整个内存回收系统崩溃。
finalize()方法是对象逃脱回收的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()跳出回收————只要重新与引用链上的任何一个对象建立关联即可,比如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时,它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的要被回收了。
5.面向对象的特征有哪些方面
答:
(抽象)、继承、封装、多态
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么
继承:继承是从已有类得到继承信息创建类的过程。提供继承的类叫父类(基类)、得到继承的类叫子类(派生类)
封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口
多态:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象调用同样的方法但是做了不同的事情。实现多态需要做两件事:1.方法重写(子类继承父类并重写父类中的方法) 2.对象造型(用父类型引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象不同而表现出不同的行为)
6.解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法
答:
栈控件操作起来最快但是栈很小,通常大量的对象都是放在堆空间
String str = new String("hello");
上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而"hello"这个字面量放在静态区
7.Math.round(11.5)等于多少? Math.round(-11.5)等于多少?
答:
Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11.四舍五入的原理是在参数上加0.5,然后向下取整
8.用最有效率的方法计算2乘以8?
答:
2 << 3(左移3位相当于乘以2的3次方,右移3位相当于乘以2的3次方)
9.构造器是否可被重写?
答:
构造器不能被继承,因此不能被重写,但可以被重载。
10.两个对象值相同(x.equals(y) == true), 但却可有不同的hashcode,这句话对不对?
答:
不对,如果两个对象x和y满足(x.equals(y) == true),它们的hashcode应当相同。Java对于equals方法和hashCode()方法时这样规定的:1.如果两个对象相同(equals()返回true),那么它们的hashCode值一定相同;2.如果两个对象的hashCode相同,两个对象不一定相同
equals返回true是是两个对象hashcode相同的充分不必要条件
11.抽象类和接口有什么异同
答:
抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。
一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类任然需要被声明为抽象类。
接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。
抽象类中的成员可以是private、default、protected、public的,而接口中的成员全都是public的。
抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。
有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法
12.Jdk与Jre与Jvm
答:
JDK :(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
JRE :(Java Runtime Environment),Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
JVM :(Java Virtual Machine), Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心
这三者的关系是:一层层的嵌套关系。JDK>JRE>JVM。
13.用for循环对二维数组赋值时,a[i][j] =1和 a[j][i]=1有什么区别
for (int i = 0; i < LEN; i++) {
for (int j = 0; j < LEN; j++) {
arr[i][j] = 1;
}
}
for (int i = 0; i < LEN; i++) {
for (int j = 0; j < LEN; j++) {
arr[j][i] = 1;
}
}
答:
a[i][j]的运行效率比a[j][i]高,这里涉及到内存的两种存储模式,行优先存储和列优先存储,这两种存储并没有什么优劣之分,但涉及到对内存中数据的最佳存储访问方式。因为在内存中,程序访问的内存地址之间连续性越好,程序的访问效率就越高。所以我们需要根据编译器的优先机制来选择是行优先的数据存储还是列优先的数据存储。而Java的数据存储是一种伊利夫向量,它通常将元素存储在连续的同一行中,这其实有点像行存储。所以如果在java中运行上述的代码,那arr[i][j]的存储效率将比arr[j][i]高很多。
典型的行优先存储编译器:C/C++
典型的列优先存储编译器:R,Matlab
14.Thread.Sleep(0)有什么用
答:
Thread.Sleep方法是告诉操作系统,在未来多少毫秒内,我不参与CPU的竞争。但sleep的线程在时间结束后不一定能够拿到CPU的使用权,需要由系统重新判定给哪个线程。Thread.Sleep(0)的作用就是触发操作系统“立刻重新进行一次CPU竞争”,可以防止防止程序进入假死状态。
1.Hadoop组成
答:
Hadoop是一个由HDFS、MapReduce、Yarn组成的分布式系统基础架构
HDFS:一个高可靠、高吞吐量的分布式文件系统
MapReduce:分布式的离线并行计算框架
YARN:作业调度与集群资源管理的框架
2.MapReduce定义
答:
MapReduce是一个分布式运算程序的编程框架,是用户开发"基于hadoop的数据应用"的核心框架
MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上
3.MapReduce架构概述
答:
MapReduce将计算过程分为两个阶段:Map和Reduce
1.Map阶段并行处理输入数据
2.Reduce阶段对Map结果进行汇总
4.MapReduce的优缺点有哪些?
答:
优点:
1.MapReduce易于编程。它简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的PC机器上运行。也就是说,我们写一个分布式程序,跟写一个简单的串行程序是一模一样的。就是因为这个特点使得MapReduce编程变得非常流行
2.良好的拓展性。当我们的计算资源不能得到满足的时候,我们可以通过简单的增加机器来拓展它的计算能力。
3.高容错性。MapReduce设计的初衷就是使程序能够部署在廉价的PC机器上,这就要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一个节点上运行,不至于使这个任务运行失败,而且这个过程不需要人工参与,而完全是由Hadoop内部完成的。
4.适合PB级以上海量数据的离线处理。
缺点:
MapReduce不擅长做实时计算、流式计算、DAG(有向图)计算
1.实时计算。MapReduce无法像MySql一样,在毫秒或者秒级内返回结果
2.流式计算。流式计算的输入数据是动态的,而MapReduce的输入数据集是静态的,不能动态变化。这是因为MapReduce自身的设计特点决定了数据源必须是静态的
3.DAG(有向图)计算。多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。在这种情况下,MapReduce并不是不能做,而是使用后,每个MapReduce作业的输出结果都会写入到磁盘,会成大量的磁盘IO,导致性能非常的低下。
ps:磁盘IO:磁盘的读写(输入、输出)
5.MapReduce核心思想是什么?
答:
分布式的运算程序需要分成至少两个阶段
第一个阶段的maptask并发实例,完全并行运行,互不相干
第二个阶段的reduce task并发实例互不相干,但是他们的数据依赖于上一个阶段的所有maptask并发实例的输出
MapReduce编程模型只能包含一个map阶段和一个reduce阶段,如果用户的业务逻辑非常复杂,那就只能多个MapReduce程序串行运行
6.MapReduce进程有哪些?
答:
一个完整的MapReduce程序在分布式运行时有三类实例进程:
1.MrAppMaster:负责整个程序的过程调度及状态协调
2.MapTask:负责map阶段的整个数据处理流程
3.ReduceTask:负责reduce阶段的整个数据处理流程
7.Hadoop2.1为什么要序列化?
答:
因为序列化可以存储“活的”对象,可以将“活的”对象发送到远程计算机
8.什么是序列化?
答:
序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输。
反序列化就是将收到字节序列(或其他数据传输协议)或者硬盘的持久化数据,转换成内存中的对象
9.为什么不用java的序列化?
答:
Java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系等),不便于在网络中高效传输。所以,hadoop自己开发了一套序列化机制(Writable),精简、高效。
10.为什么序列化对hadoop很重要?
答:
因为Hadoop在集群之间进行通许或者RPC调用的时候,需要序列化,而且要求序列化要快,且体积要小,占用带宽要小。所以必须理解Hadoop的序列化机制。
序列化和反序列化在分布式数据处理领域经常出现:进程通信和永久存储。然而Hadoop中各个节点的通信是通过远程调用(RPC)实现的,RPC序列化要求具有以下特点:
1.紧凑:紧凑的格式能让我们充分利用网络带宽,而带宽是数据中心最稀缺的资源
2.快速:进程通信形成了分布式系统的骨架,所以需要尽量减少序列化和反序列化的性能开销,这是基本的
3.可拓展:协议为了满足新的需求变化,所以控制客户端和服务器过程中,需要直接引进相应的协议,这些是新协议,原序列化方式能支持新的协议报文
4.互操作:能支持不同语言写的客户端和服务端进行交互。
11.MapReduce工作流程
答:
1.maptask收集我们的map()方法输出的kv对,放到内存缓冲区中
2.从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件
3.多个溢出文件会被合并成大的溢出文件
4.在溢出过程中,及合并的过程中,都要调用partitioner进行分区和针对key进行排序
5.reducetask根据自己的分区号,去各个maptask机器上取相应的结果分区数据
6.reducetask会取到同一个分区的来自不同maptask的结果文件,reducetask会将这些文件再进行合并(归并排序)
7.合并成大文件后,shuffle的过程也就结束了,后面进入reducetask的逻辑运算过程(从文件中取出一个一个的键值对group,调用用户自定义的reduce()方法)
12.MapReduce程序效率的瓶颈
答:
1.计算机性能:
CPU、内存、磁盘健康、网络、I/O操作优化
2.数据倾斜
3.map和reduce数设置不合理
4.map运行时间太长,导致reduce等待过久
5.小文件过多
6.大量的不可分块的超大文件
7.spill次数过多
8.merge次数过多
9.其他
13.MapReduce的优化方法
答:
从六个方面考虑:数据输入、Map阶段、Reduce阶段、IO传输、数据倾斜问题和常用的调优参数
数据输入:
1.合并小文件:在执行MR任务前将小文件进行合并,大量的小文件会产生大量的map任务装载次数,而任务的装载比较耗时,从而导致MR运行较慢
2.采用CombineTextInputFormat来作为输入,解决输入端大量小文件场景
Map阶段:
1.减少溢写(spill)次数:通过调整io.sort.mb及sort.spill.percent参数值,增大触发spill的内存上限,减少spill次数,从而减少磁盘IO
2.减少合并(merge)次数:通过调整io.sort.factor参数,增大merge的文件数目,减少merge的次数,从而缩短MR处理时间
3.在map之后,不影响业务逻辑前提下,先进行combine处理,减少I/O
Reduce阶段:
1.合理设置map和reduce数:两个都不能设置少,也不能设置太多。太少,会导致task等待,延长处理时间;太多,会导致map、reduce任务间竞争资源,造成处理超市等错误
2.设置map、reduce共存:调整slowstart.completedmaps参数,使map运行到一定程度后,reduce也开始运行,减少reduce的等待时间。
3.规避使用reduce:因为reduce在用于连接数据集的时候将会产生大量的网络消耗。
14.NameNode & Secondary NameNode 工作机制
答:
第一阶段:NameNode启动
1.第一次启动NameNode格式化后,创建fsimage和edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存
2.客户端对元数据进行增删改的请求
3.NameNode记录操作日志,更新滚动日志
4.NameNode在内存中对数据进行增删改查
第二阶段Secondary NameNode工作
1.Secondary NameNode询问NameNode是否需要checkpoint。直接带回NameNode的检查结果
2.Secondary NameNode 请求执行checkpoint
3.NameNode滚动正在写的edits日志
4.将滚动前的剪辑日志和镜像文件拷贝到Secondary NameNode
5.Secondary NameNode 加载编辑日志和镜像文件到内存,并合并
6.生成新的镜像文件fsimage.chkpoint
7.拷贝fsimage.chkpoint 到 NameNode
8.NameNode将fsimage.chkpoint重新命名为fsimage
15.DataNode工作机制
答:
1.一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳
2.DataNode启动后向NameNode注册,通过后,周期性(1小时)的向NameNode上报所有的块信息
3.心跳是每3秒一次,心跳返回结果带有NameNode给该DataNode的命令,如:复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用
16.一个DataNode宕机了,要怎么恢复 ???不对劲
答:
如果只是节点挂了,重启就可以了,如果是机器挂了,重启机器后看节点是否能重启,不能重启就要找到相应的原因来修复。但是最终的解决方案应该是在设计集群的初期就考虑到这个问题。
17.NameNode对元数据的管理
答:
NameNode对数据的管理采用了三种存储形式:
内存元数据(NameSystem)
磁盘元数据镜像文件(fsimage镜像)
数据操作日志文件(可通过日志运算出元数据)(edit日志文件)
18.元数据的checkpoint是如何运行?
答:
每隔一段时间,会由Secondary NameNode将NameNode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge,这个过程成为checkpoint
NameNode和Secondary NameNode的工作目录存储结构完全相同,所以,当NameNode故障退出需要重新恢复时,可以从Secondary NameNode 的工作目录中将fsimage拷贝到NameNode的工作目录,以恢复NameNode的元数据。
19.MapReduce中combiner和partition的作用
答:
combiner是发生在map的最后一个阶段,父类就是Reducer,意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量,缓解网络传输瓶颈,提高reducer的执行效率
partition的主要作用将map阶段产生的所有kv对分配给不同的reducerTask处理,可以将reduce阶段的处理负载进行分摊
20.什么是数据倾斜?
答:
MapReduce程序执行时,reduce节点大部分执行完毕,但是又一个或者几个reduce节点运行很慢,导致整个程序的处理时间很长,这是因为某一个key的条数比其他key多很多(有时是百倍或者千倍之多),这条key所在的reduce节点所处理的数据量比其他节点就大很多,从而导致某几个节点迟迟运行不完,这就被称为是数据倾斜。
21.MapReduce处理数据倾斜
答:
1.局部聚合+全局聚合
第一次在map阶段对那些导致了数据倾斜的key加上1到n的随机前缀,这样本来相同的key也会被分到多个Reduce中进行局部聚合,数量就会大大降低。
第二次MapReduce,去掉key的随机前缀,进行全局聚合
思想:二次MR,第一次将key随机散列到不同reducer进行处理达到负载均衡的目的。第二次再去掉key的随机前缀,按原key进行reduce处理。
这个方法要进行两次MapReduce,性能稍差
2.增加Reducer,提升并行度
JobConf.setNumReduceTasks(int);
3.实现自定义分区
根据数据分布情况,自定义散列函数,将key均匀分配到不同Reducer上。
22.对于shuffle阶段,是怎样理解的?
答:
shuffle:洗牌、发牌
核心机制:缓存、数据分区、排序、Merge进行局部value的合并
具体来说:就是将maptask输出的处理结果数据,分发给reducetask,并在分发的过程中,对数据按key进行了分区和排序
1.Map方法之后 Reduce方法之前这段处理过程叫Shuffle
2.Map方法之后,数据首先进入到分区方法,把数据标记好分区,然后把数据发送到环形缓冲区,环形缓冲区默认大小100M,环形缓冲区达到80%时,会进行溢写;溢写前对数据进行排序,排序按照对key的索引进行字典顺序排序,用快排进行排序;溢写过程会产生大量的溢写文件,需要对溢写文件进行归并排序;对溢写的文件也可以进行Combiner操作,但是汇总操作、求平均值不行。最后将文件按照分区存储到磁盘中,等待Reduce端拉取
3.每个Reduce拉取Map端对应分区的数据。拉取数据后先存储到内存中,内存不够了,再存储到磁盘。拉取完所有数据后,采用归并排序将内存和磁盘中的数据都进行排序
在进入Reduce方法前,可以对数据进行分组操作
23.MapReduce的map数量和reduce数量是由什么决定的,怎么配置?
答:
Map的数量由输入切片的数量决定,有多少个切片就有多少个mapTask
Reduce数量自己配置 默认是1
24.MapReduce的优化
答:
1.设置合理的map和reduce的个数。合理设置blocksize
2.避免出现数据倾斜
3.combiner函数
4.对数据进行压缩
5.小文件处理优化:事先合并成大文件 combineTextInputformat,在hdfs上用MapReduce将小文件合并成SequenceFile大文件(key:文件名,value:文件内容)
6.参数优化
25.MapReduce的运行流程
答:
1.一个MapReduce程序启动的时候,最先启动的是MRAppMaster,MRAppMaster启动后根据本次job的描述信息,计算出需要的maptask实例数量,然后向集群申请机器启动相应数量的mapTask进程
2.MapTask进程启动之后,根据给定的数据切片范围进行数据处理,主体流程:
2.1利用用户指定的inputformat来获取RecordReader读取数据,形成输入KV对
2.2将输入KV对传递给客户定义的map()方法,做逻辑运算,并将map()方法输出的KV对收集到缓存
2.3将缓存中的KV对按照K分区排序后不断溢写到磁盘文件
3.MRAppMaster监控到所有maptask进程任务完成之后,会根据用户指定的参数启动相应数量的reducetask进程,并告知reducetask进程要处理的数据范围(数据分区)
4.Reducetask进程启动之后,根据MRAppMaster告知的待处理数据所在位置,从若干台maptask运行所在机器上获取到若干个maptask输出结果文件,并在本地进行重新归并排序,然后按照相同key的KV为一个组,调用客户定义的reduce()方法进行逻辑运算,并收集运算输出的结果KV,然后调用客户指定的outputFormat将结果输出到外部存储
26.Hadoop优化有哪些方面
答:
HDFS小文件
减少文件的小文件数量,对文件进行合并等操作
数据输入小文件处理
1.合并小文件:对小文件进行归档、自定义Inputformat将小文件存储成SequenceFile文件
2.采用ConbinFileInputFormat来作为输入,解决输入端大量小文件场景
3.对于大量小文件Job,可以开启JVM重用
Map阶段
1.增大环形缓冲区大小。由100M扩大到200M
2.增大环形缓冲区溢写的比例。由80%扩大到90%
3.减少对溢写文件的merge次数
4.不影响实际业务的前提下,采用Combiner提前合并,减少I/O
Reduce阶段
1.合理设置Map和Reduce数:两个都不能设置太少,也不能设置太多。太少会导致Task等待,延长处理时间;太多,会导致Map、Reduce任务间竞争资源,造成处理超时等错误
2.设置Map、Reduce共存:调整slowstart.completedmaps参数,使Map运行到一定程度后,Reduce也开始运行,减少Reduce的等待时间
3.规避使用Reduce,因为Reduce在用于连接数据集的时候将会产生大量的网络消耗
4.增加每个Redcue去Map中拿数据的并行数
5.集群性能可以的前提下,增大Reduce端存储数据内存的大小
IO传输
1.采用数据压缩的方式,减少网络IO的时间
2.采用SequenceFile二进制文件
整体
1.MapTask默认内存大小为1G,可以增加MapTask内存大小为4~5g
2.ReduceTask默认内存大小为1G,可以增加ReduceTask内存大小为4~5g
3.可以增加MapTask的cpu核数,增加ReduceTask的CPU核数
4.增加每个Container的CPU核数和内存大小
5.调整每个MapTask和ReduceTask最大重试次数
1.HDFS写流程
1.client跟NameNode通信请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在
2.NameNode返回是否可以上传
3.client请求第一个block该传输到哪些DataNode节点上
4.NameNode返回3个DataNode节点A,B,C(第一个副本会有就近原则)
5.client请求3台DataNode中的一台A上传数据(本质上是一个RPC调用),A收到请求会继续调用B,然后B调用C,将整个pipeline建立完成,再逐级返回客户端
6.client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C(并不是传递完一个block才开始传第二个节点);A每传一个packet会放入一个应答队列等待应答
7.当一个block传输完成之后,client再次请求NameNode上传第二个block的服务器
8.每个DataNode写完一个block块后,会返回确认信息
9.写完数据后,关闭输出流
10.DataNode发信号给NameNode汇报自己已经写完了
2.Hdfs读流程
1.client跟NameNode通信查询元数据,找到文件块所在的DataNode服务器
2.挑选一台就近的DataNode节点,请求建立socket流
3.DataNode开始发送数据(从磁盘里面读取数据放入流中,以packet为单位来做校验)
4.数据以packet为单位
3.HDFS小文件弊端
答:
HDFS上每个文件都要在namenode上建立一个索引,这个索引的大小约为150byte,这样当小文件比较多的时候,就会产生很多的索引文件,一方面会大量占用namenode的内存空间,另一方面就是索引文件过大使得索引速度变慢
解决方案:
Hadoop Archive:
是一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样就减少namenode的内存使用
Sequence file:
Sequence file 由一些列的二进制key/value组成,如果key为文件名,value,则可以将大批小文件合并成一个大文件。
CombineFileInputFormat:
CombineFileInputFormat是一种新的inputformat,用于将多个文件合并成一个单独的split,另外,它会考虑数据的存储位置
开启JVM重用
对于大量小文件Job,可以开启JVM重用会减少45%运行时间
PS:JVM重用:一个map运行一个jvm,重用的话,一个jvm在一个map上运行完毕后,这个jvm继续运行其他map。
4.HDFS优缺点?
答:
优点:
1.高容错性
1.1数据自动保存多个副本
1.2某一个副本丢失以后,它可以自动恢复
2.适合大数据处理
2.1能够处理数据规模达到GB、TB、甚至PB级别的数据
2.2能够处理百万规模以上的文件数量
3.流式访问数据
3.1一次写入,多次读取,不能修改,只能追加
3.2它能保证数据的一致性
4.可构建在廉价机器上,通过多副本机制,提高可靠性
缺点:
1.不适合低延时数据访问,比如毫秒级的存储数据,是做不到的
2.无法高效的对大量小文件进行存储
2.1存储大量小文件会占用NameNode大量的内存来存储文件、目录和块信息,这样不可取,因为NameNode的内存是有限的
2.2小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标
3.并发写入、文件随机修改
3.1一个文件只能有一个写,不允许多个线程同时写
3.2仅支持数据append(追加),不支持文件的随机修改
5.HDFS架构是由哪些部分组成的?
答:
主要由四个部分组成,分别为HDFS Client、NameNode、DataNode和Secondary NameNode
Client: 就是客户端
1.文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行存储
2.与NameNode交互,获取文件的位置信息
3.与DataNode交互,读取或者写入数据
4.Client提供一些命令来管理HDFS,比如启动或者关闭HDFS。
5.Client可以通过一些命令来访问HDFS
NameNode:就是master 它是一个主管、管理者
1.管理HDFS的名称空间
2.管理数据块(block)映射信息
3.配置副本策略
4.处理客户端读写请求
DataNode:就是Slave NameNode下达命令,DataNode执行实际的操作
1.存储实际的数据块
2.执行数据块的读/写操作
Secondary NameNode:并非NameNode的热备份。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务
1.辅助NameNode,分担其工作量
2.定期合并Fsimage和Edits,并推送给NameNode
3.在紧急情况下,可辅助恢复NameNode
6.129M的数据在HDFS中存储会有几个block块?
答:
1个,因为hdfs允许文件分块中的最后一个block有一定的超过,只要不超过128M的1.1倍,也就是只要不超过140.8M都可以存在一个块中
7.在通过客户端向hdfs中写数据的时候,如果某一台机器宕机了,会怎样处理?
答:
先判断宕机的节点是不是正在写入的节点,如果不是,那就按正常流程恢复节点即可,如果是的话,那么正在写入的数据会放置到queue的顶部,并将挂掉的DataNode移出pipline,将数据写入到剩余的DataNode中,在写入结束后,NameNode会手机DataNode的信息,发现此文件的副本数没有达到配置的要求,然后会寻找一个DataNode保存副本。
8.HDFS数据安全性如何保证?
答:
1.存储在HDFS系统上的文件,会分割成128M大小的block存储在不同的节点上,block的副本数默认3份,也可配置成更多份
2.第一个副本一般放置到与client较近的一个节点上,第二个副本放置到与第一个副本同一个机架的不同节点,第三个副本放到不同机架的节点上
3.DataNode以block为单位,每3s报告心跳状态,如果10min内不报告心跳状态则NameNode认为block已死掉,NameNode会把其上面的数据备份到其他一个DataNode节点上,保证数据的副本数量
4.DataNode会默认每小时把自己节点上的所有块状态信息报告给NameNode
5.采用safemode模式:DataNode会周期性的报告block信息,NameNode会计算block的损坏率,当阀值<0.999f时系统会进入安全模式,HDFS只读不写。HDFS元数据采用secondaryNameNode备份或者HA备份
1.Yarn的资源调度流程
答:
1.用户向YARN中提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序
2.ResourceManager为该应用程序分配第一个Container,并与对应的NodeManager通信,要求它在这个Container中启动应用程序的ApplicationMaster
3.ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceMananger查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~7
4.ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源
5.一旦ApplicationMaster申请到资源后,便与对应的NodeManager通信,要求它启动任务
6.NodeManager为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务
7.各个任务通过某个RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。在应用程序运行过程中,用户可随时通过RPC向ApplicationMaster查询应用程序的当前运行状态。
8.应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己
1.什么是Hive
答:
Hive是Facebook开源用于解决海量结构化日志的数据统计
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能
本质是:将HQL转化成MapRedcue程序
相关概念:
1.Hive处理的数据存储在HDFS上
2.Hive分析数据底层的实现是MapReduce
3.执行程序运行在Yarn上
2.Hive的优缺点
答:
优点:
1.操作接口采用类SQL语法,提供了快速开发的能力(简单、容易上手)
2.避免了去写MapReduce,减少开发人员的学习成本
3.Hive在处理大数据方面有优势
4.Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数
缺点:
1.Hive的HQL表达能力有限
1.迭代式算法无法表达
2.数据挖掘方面不擅长
2.Hive的效率比较低
1.Hive自动生成的MapRedcue作业,通常情况下不够智能化
2.Hive调优比较困难,粒度较粗
3.Hive的执行延迟比较高,因此处理小数据没有优势,且常用于对实时性要求不高的场合
3.udf 、 udaf 、 udtf 区别
答:
UDF操作作用于单个数据行,并且产生一个数据行作为输出。大多数函数都属于这一类(比如数学函数和字符串函数)
UDAF接受多个输入数据行,并产生一个输出数据行。像COUNT和MAX这样的函数就是聚集函数
UDTF操作单个数据行,并且产生多个数据行-------一个表作为输出
简单说:
UDF:返回对应值 一对一
UDAF:返回聚类值 , 多对一
UDTF:返回拆分值 , 一对多
4.hive有哪些保存元数据的方式,各有什么特点
答:
内存数据库derby,按照小,但是数据存储在内存,不稳定
mysql数据库,数据存储模式可以自己设置,持久好,查看方便
5.生成环境中为什么建议使用外部表
答:
1.因为外部表不会加载数据到hive,减少数据传输,数据还能共享
2.hive不会修改数据,所以无需担心数据的损坏
3.删除表时,只删除表结构,不删除数据
6.insert into 和override write 的区别
答:
insert into :将数据写到表中
override write: 覆盖之前的内容
7.hive中的判断函数有哪些
答:
if 、 coalesce 、 case
8.四个by的区别
答;
Sort By :分区内排序
Order By:全局排序,只有一个Reducer
Distribute by:类似MR中Partition , 进行分区,结合sort by使用
Cluster By:当Distribute by和Sort by 字段相同时,可以使用Cluster by。Cluster by除了具有Distribute by的功能还兼有Sort by的功能。但是排序只能是升序排序,不能指定排序规则。
9.Hive里字段的默认分割符是什么?
答:
\001
10.分区分桶的区别,为什么要分区
答:
分区表:原来的一个大表存储的时候分成不同的数据目录进行存储。如果说是单分区表,那么在表的目录下就只有一级子目录,如果说是多分区表,那么在表的目录下有多少分区就有多少级子目录。不管是单分区表、还是多分区表,在表的目录下,和非最终分区目录下是不能直接存储数据文件的
分桶表:原理和hashPartitioner一样,将hive中的一张表的数据进行归纳分类的时候,归纳分类规则就是hashpartitioner。(需要指定分桶字段,指定分成多少桶)
分区表和分桶的区别除了存储的格式不同外,最主要的是作用:
分区表:细化数据管理,缩小mapreduce程序 需要扫描的数据量
分桶表:提高join查询的效率,在一份数据会被警察用来做连接查询的时候建立分桶,分桶字段就是连接字段;提高采样的效率
1.zookeeper是什么
答:
zookeeper是一个开放源码的分布式协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
分布式应用程序可以基于zookeeper实现诸如数据发布、负载均衡、命名服务、分布式协调、集群管理、Master选举等功能。
并且zookeeper还保证了分布式的一些特性,如:
顺序一致性
原子性
单一视图
可靠性
最终一致性
2.zookeeper提供了什么?
答:
文件系统
通知机制
3.简单描述一下zookeeper的文件系统
答:
zookeeper提供了一个多层级的节点命名空间(节点称为znode),与windows、linux的文件系统不同的是,znode可以设置关联的数据,而windows,linux的文件系统中只有文件节点可以存放数据,目录节点不行。
zookeeper为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得zookeeper不能用于存放大量的数据,每个节点的存放数据上限为1M,最好不超过1KB
4.zookeeper的ZAB协议是什么?
答:
ZAB协议是为zookeeper专门设计的一种支持崩溃恢复的原子广播协议。
ZAB协议包括两种基本的模式:崩溃恢复和消息广播。
当整个zookeeper集群刚刚启动或者leader无夫妻宕机、重启或者网络故障导致不存在过半的服务器与Leader服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式,首先选举产生新的Leader服务器,然后集群中Follower服务器开始与新的Leader服务器进行数据同步,当集群中超过半数机器与该leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,leader服务器开始接收客户端的事务请求、生成事务提案来进行事务请求处理。
5.zookeeper有几种类型的数据节点:
答:
四种
Persistent - 持久节点
除非手动删除,否则节点一直存在于zookeeper上
Ephemeral - 临时节点
临时借点的声明周期与客户端会话绑定,一旦客户端会话失效,那么这个客户端创建的所有临时借点都会被移除 (客户端与zookeeper连接断开,会话不一定会失效)
Persistent_Sequential - 持久顺序节点
基本特性同持久节点,只是增加了顺序属性,节点名会有一个由父节点维护的自增整数型数字后缀
Ephemeral_Sequential - 临时顺序节点
基本特性同临时节点,增加了顺序属性,节点名后会有一个由父节点维护的自增整数型数字后缀
6.zookeeper的leader选举
答:
服务器启动时期的leader选举
1.每个Server会发出一个投票。由于是初始阶段,每个Server都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和zxid,然后各自将这个投票发给集群中的其他机器
2.接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如:检查是否是本轮投票、是否来自Looking状态的服务器
3.处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK对比,优先检查ZXID,ZXID比较大的服务器优先作为Leader。如果ZXID相同,则比较myid。myid较大的服务器作为Leader服务器。由于此时处于服务器启动的初始阶段,各个服务器的ZXID都相同,所以会比较myid,因此myid小的Server会更新自己的投票为myid大的服务器,然后重新投票,而myid大的服务器无需更新投票,只是再次向集群中的所有机器发出上一次的投票信息即可。
4.统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,如果有过半的接受到了相同的投票信息,则认为已经选出了Leader。
5.改变服务器状态。一旦确定了Leader,每个服务器都会更新自己的状态,如果是Foller,则变更为Following,如果是Leader,就变更为leading
服务器运行期间的Leader选举
1.变更状态。Leader挂后,其他非Observer服务器都会将自己的服务器状态变更为Looking,然后开始进入选举过程
2.每个Server发出一个投票。在运行期间,每个服务器上的zxid可能不同,所以在第一轮投票中,每个服务器都会将票投给自己,把自己的myid和zxid发送到集群中的所有服务器上。
3.处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK对比,优先检查ZXID,ZXID比较大的服务器优先作为Leader。如果ZXID相同,则比较myid。myid较大的服务器作为Leader服务器。各个服务器根据PK结果发起新一轮的投票
4.统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,如果有过半的接受到了相同的投票信息,则认为已经选出了Leader。
5.改变服务器状态。一旦确定了Leader,每个服务器都会更新自己的状态,如果是Foller,则变更为Following,如果是Leader,就变更为leading
1.什么是flume?
答:
1.flume是一个分布式的、可靠的、高可用的海量日志采集、聚合和传输的系统
2.flume可以采集文件,socket数据包等各种形式源数据,又可以将采集到的数据输出到HDFS、Hbase、hive、kafka等众多外部存储系统中
3.一般的采集需求,通过对flume的简单配置即可实现
4.flume针对特殊场景也具备良好的自定义扩展能力,因此,flume可以适用于大部分的日常数据采集场景
2.flume架构
答:
1.Flume分布式系统中最核心的角色是agent,flume采集系统就是由一个个agent所连接起来形成的
2.每一个agent相当于一个数据传递员,其内部有三个组件:
1.source:采集源,用于跟数据源对接,以获取数据
2.sink:下沉地,采集数据的传送目的,用于往下一级agent传递数据或者往最终存储系统传递数据
3.Channel:agent内部的数据传输通道,用于从source将数据传递到sink
3.flume的优势
答:
1.Flume可以将应用产生的数据存储到任何集中存储器中,如:hdfs,hbase
2.当手机数据的速度超过写入数据的速度的时候,这时,flume会在source和channel之间进行缓存,保证数据不会丢失
3.Flume的管道是基于事务的,保证了数据在传送和接收时的一致性
4.Flume是可靠地,容错性高的、可升级的、易管理的、并且可定制的
4.Flume的特征:
答:
1.Flume可以高效率的将多个网站服务器中手机的日志信息存入HDFS/HBase中
2.使用Flume,我们可以将从多个服务器中获取的数据迅速的移交给hadoop
3.支持各种输入和输出数据的类型
4.支持多路径流量、多管道接入流量、多管道接出流量
5.可以被水平扩展
5.flume调优
答:
source:
1.增加source个数:可以增大source读取能力
具体做法:如果一个目录下生成的文件过多,可以将它拆分成多个目录。每个目录都配置一个source
2.增大batchSize:可以增大一次性批处理的event条数,适当调大这个参数,可以调大这个参数,可以跳高soucer搬运数据到channel的性能。
channel:
1.memory:性能好,但是,如果发生意外,可能丢失数据
2.使用file channel时,dataDirs配置多个不同盘下的目录可以提高性能
3.transactionCapacity 需要大于source和sink的batchSize参数
sink:
增加sink个数可以增加消费event能力
1.Sqoop导入数据到hdfs中的参数
答:
sqoop import \
--connect jdbc:mysql://hadoop02:3306/mysql(数据库连接名) \
--username root \ (数据库用户名)
--password root \ (数据库密码)
--target-dir /home/hadoop \ (存储到hdfs中的位置)
--delete-target-dir (有个参数) \ (导入的目标目录如果存在则删除那个目录)
--num-mappers 1 \(相当于 -m ,并行导入时 map task的个数)
--fields-terminated-by '\t' \ (去除字段分隔符)
--query "SQL语句 and $CONDITIONS;" (一定要加最后的$CONDITIONS)
2.Sqoop底层运行的任务是什么
答
大多数情况下只有map阶段,在执行复杂sql语句时,会有reduce阶段
3.Sqoop 设置MapTask并行度大于1
答:
当map task并行度大于1 时,要同时调用
--split-by id 指定根据id字段切分
--m n 指定map并行度n个
1.如何进行Hbase的调优
1.建立高可用的环境
在Hbase中Hmaster负责监控RegionServer的生命周期,均衡RegionServer的负载,如果Hmaster挂掉了,那么整个集群将会陷入不健康的状态,并且此时的工作状态只能维持短暂时间。所以需要为Hbase设立高可用的环境
2.预分区
每个region维护着startRow与endRowKey,如果加入的数据符合某个region维护的rowKey范围,则该数据交给这个region维护,那么一招这个原则,我们可以将数据所要投放的分区提前大致的规划好,可以提高Hbase的性能
3.优化RowKey设计
与预分区的原因相同,为了让数据均匀分布在所有的region中,尽量避免数据倾斜,对RowKey进行优化设计
4.内存优化
Hbase操作过程中需要大量的内存开销,因为Table是可以缓存在内存中的,可以分配给Hbase多一点的内存,提高运行效率,但是不建议分配非常大的堆内存,因为GC过程持续太久会导致RegionServer处于长期不可用的状态。
2.Hbase的rowkey怎么设计比较好?列族怎么设计比较好?
答:
设计原则:
1.RowKey长度原则
2.RowKey散列原则
3.RowKey唯一原则
如何设计:
1.生成随机数、hash、散列值
2.字符串反转
3.字符串拼接
3.hbase过滤器的用途
答:
1.增强Hbase查询数据的功能
2.减少服务端返回给客户端的数据量
4.Hbase宕机如何处理
答:
宕机分为HMaster宕机和HRegioner宕机
如果是HRegioner宕机,HMaster会将其所管理的region重新分布到其他活动的RegionServer上,由于数据和日志都持久存储在HDFS中,该操作不会导致数据丢失,所以数据的一致性和安全性是有保障的。
如果是HMaster宕机,HMaster没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper的选举机制保证总有一个Master运行。即zookeeper会保证总会有一个HMaster在对外提供服务
5.hive和hbase的区别
答:
共同点:
1.hbase与hive都是架构在hadoop之上的,都是用hdfs作为底层存储。
区别:
1.hive建立在Hadoop之上是为了减少MapReduce jobs编写工作的批处理系统,HBase是为了弥补Hadoop对实时操作的缺陷。
2.Hive本身不存储和计算数据,它完全依赖于HDFS和MR,Hive中的表纯逻辑
3.Hbase是物理表,不是逻辑表,提供一个超大的内存hash表(meta表),搜索引擎通过它来存储索引,方便查询操作
6.HBase写流程
答:
1.客户端要连接zookeeper,从zk的/hbase节点找到hbase:meta表所在的RegionServer
2.RegionServer扫描HBase:meta中的每个region的起始行键,对比要插入的数据在哪个region的范围里
3.从对应info:server Key中存储了region是由哪个RegionServer在负责
4.客户端直接请求对应的RegionServer
5.RegionServer接收到客户端发来的请求之后,就会将数据写入到region中
7.Hbase读流程
答:
1.首先Client连接zookeeper,找到hbase:meta表所在的RegionServer
2.请求对应的RegionServer,扫描hbase:meta表,根据namespace、表名和rowkey在meta表中找到数据所在的region
3.根据这个region找到对应的RegionServer
4.请求对应的RegionServer,扫描指定的region返回数据到Client(先内存,后磁盘)
8.HBase数据flush过程
答:
1.当MemStore数据达到阈值(默认是128M,老版本是64M) , 将数据刷到硬盘,将内存中的数据删除,同时删除HLog中的历史数据
2.将数据存储到HDFS中
3.在HLog中做标记点
9.数据合并过程
答:
1.当数据块达到4块,hmaster将数据块加载到本地,进行合并
2.当合并的数据超过256M,进行拆分,将拆分后的region分配给不同的RegionServer管理
3.如果RegionServer宕机了,会将RegionServer上的hlog拆分,然后分配给不同的RegionServer加载,修改META表
4.hlog会同步到hdfs
10.Hmaster和RegionServer职责
答:
Hmaster:
1.管理用户对Table的增、删、改、查
2.记录region在哪台RegionServer上
3.在Region Split后,负责新Region的分配
4.新机器加入时,管理HRegionServer的负载均衡,调整Region分布
5.在HRegionServer宕机后,负责失效RegionServer上的Region的迁移
HRegionServer:
1.响应用户I/O请求,向HDFS中读写数据
2.管理Region
11.HBase列族和Region的关系
答:
Hbase中有多个RegionServer,每个RegionServer里有多个Region,一个Region中存放着若干行的rowkey以及对应的数据,一个列族就相当于一个文件夹,如果经常要搜索整个一条数据,列族越少越好,如果只有一部分的数据需要经常被搜索,那么将经常搜索的数据建立一个列族,其他不常搜索的建立列族,这样可以提升搜索效率。
12.如何避免读、写Hbase时造成访问热点问题
答:
1.加盐
给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。加盐后的rowkey就会根据随机生成的前缀分散到各个region上,类似于hive的分桶,MR的分区。
2.哈希
哈希会使同一行永远用一个前缀加盐。哈希也可以使负载均衡。
3.反转
反转固定长度或者数字格式的rowkey,使得rowkey中经常变化的部分放在前面,牺牲了rowkey的有序性
4.时间戳反转
使用反转的时间戳作为rowkey的一部分
5.尽量减少行和列的大小
Hbase中,value永远和她的key一起传输的。如果rowkey和列名很大,Hbase storefiles中的索引会占据Hbase分配的大量内存,因为具体的值和它的key很大。可以修改表的模式以减小rowkey和列名的大小。