飞道的博客

大数据常见面试题(一)

170人阅读  评论(0)

一、当前集群环境

CDH 6.3.3
hadoop 3.0.0
hbase 2.1.0
hive 2.1.1
impala 3.2.0
spark 2.4.0
kafka 2.2.1
scala 2.11.12

二、hadoop

1.Hdfs的工作原理(读和写)★★★★★

读:client请求namenode ,获取目标文件的元数据信息,namenode校检无误后,返回给client,client根据元数据与就近的datanode建立连接,获取block 块,并将block 块合并后,返回给client。

写:client 向 namenode发出写 的请求,namenode 检查是否路径存在,权限等,通过后,将操作写入editLog,并返回一个节点列表,给client,client根据元数据与列表中就近的DataNode进行连接,并将data与返回的节点列表一并发送给它,此后,client就与所有的DataNode节点建立 piepline管道,一个DataNode写完后会传给下一个DataNode,每个DataNode写完一个 block 后,会返回确认信息给namenode。同时进行下一个 block的写入,直到全部写入完成。

2.MapReduce的原理 ★★★★★

MR把拿到的 split 分配给相应的 task,每个task处理对应的split,split 以line的方式读取每一行数据,将这些数据加载到一个环形缓冲区中,当环形缓冲区达到 80%的时候,会将这些数据溢写到磁盘中,同时按照 k-v的方式进行分区,(默认采用hashpartition),同时在每个分区内进行排序,如果这时设置了setcombinerclass,则会对每个分区的数据进行combiner操作,还可以设置 output-compress,对数据进行压缩,最后merge,根据分区规则,将数据归并到同一个文件中,等待reduce端拉取,等到所有的maptask 任务结束后,会根据分区数量启动相应的数量的reduceTask,每个reducetask 从mapTask机器上拷贝相应分区的数据到本地的缓冲区,缓冲区不够就溢写到磁盘,待所有数据拷贝完毕后,进行归并排序,之后按照相同的key分组,最后调用 reduce() 方法进行聚合处理,生成的结果将以文件形式在hdfs中体现。

3.Yarn的工作流程 ★★★★★

1.client 提交一个任务到Yarn,包括用户程序、 相关文件、applicationMasrer程序、启动AM(applicationMaster)命令。

2.RM(Resource Manager)分配第一个 container,并与所在的 NM(nodeManager)进行 通信,要求NM在container中启动 AM。

3.AM向RM注册自己,这样用户可以通过 RM查看程序的运行状态等,然后它准备为程序的各个任务申请资源,并监控他们的 运行状态直到任务结束。

4.AM以轮询的方式通过RPC协议与RM通信,申请和领取资源。

5.AM领取到资源后,会向申请到的Container所在的NM进行通信,要求NM在container中启动任务。

6.任务启动。NM为要启动的任务配置好环境变量、jar包、二进制文件等,并将启动命令写在一个脚步中,通过改脚步运行任务。

7.NM与相应的AM保持RPC通信,汇报自身任务的运行进度与状态,以让AM在任务失败时,可以重启任务。

8.任务结束,AM向RM通信,要求注销和关闭自己。

4.各个组件的作用 ★★★

NameNode: 集群的主节点,保存元数据、副本数、文件目录树等信息

DataNode:真正存放数据的节点,汇报block块的状态

SceondNameNode: 检查点节点,NameNode日志高可用的关键,定期的对 edits 文件和 FsImage 文件进行合并,防止元数据丢失

Edits:记录数据的写操作,体现了HDFS的最新状态

fsImage: 集群中元数据的一个永久性检查点,用于故障恢复

5.为什么引入SecondNameNode ★

因为只有集群重启时,edits 才会和 FsImage 文件进行合并,因此为了防止 edit文件越来越大,导致重启时,文件的合并耗时过长,因此引入 检查点机制。

6.NameNode 元数据的持久化机制 ★★

“Fsimage" 和”Edits",SecondaryNameNode 定期 对 FsImage 和 Edits文件的合并来保证NameNode中数据的高可用

7.如果client从DataNode上读取block时网络中断了如何解决? ★

此时我们会找到block另外的副本(一个block块有3个副本),并且通过FSData InputStream进行记录,以后就不再从中断的副本上读了。

8.如果一个DataNode挂掉了怎么办? ★

由于心跳机制的存在,dataNode 会定时向 nameNode 发送blockReport ,一旦dataNode 挂掉后,nameNode,会在其余副本所在节点向 nameNode 报告时,向其他的副本所在的任一节点发送指令,使其拷贝本身的副本给另外的正常节点,保证副本数量为设定的值。

9.client如何保证读取数据的完整性 ★

因为从DataNode上读数据是通过网络来读取的,这说明会存在读取过来的数据是不完整的或者是错误的情况。
DataNode上存储的不仅仅是数据,数据还附带着一个叫做checkSum检验和(CRC32算法)的概念,针对于任何大小的数据块计算CRC32的值都是32位4个字节大小。此时我们的FSData InputStream向DataNode读数据时,会将与这份数据对应的checkSum也一并读取过来,此时FSData InputStream再对它读过来的数据做一个checkSum,把它与读过来的checkSum做一个对比,如果不一致,就重新从另外的DataNode上再次读取。

之后FSData InputStream会告诉NameNode,这个DataNode上的这个block有问题了,NameNode收到消息后就会再通过心跳机制通知这个DataNode删除它的block块,然后再用类似上面3中的做法,让正常的DataNode去copy一份正常的block数据给其它节点,保证副本数为设定值。

三、Hbase

1.Hbase的架构 ★★★★

粗略来说:Hbase 主要由 ZooKeeper,HMaster , HRegion Server 三部分组成。

Hbase Master 负责Region的分配,DDL(创建,删除table)等操作

Region Server 负责处理数据的读写请求,客户端请求数据时直接和 Region Server 交互

zookeeper 负责维护和记录Hbase集群状态

2.RowKey的设计原则 ★★★★★

1.长度限制 (最好16字节内)

2.散列原则(rowKey要打散,避免热点写)

3.唯一性

3.RowKey怎么设计以规避热点写 ★★★★

1.加盐 (rowKey 前添加随机数)

2.hash

3.反转、时间戳反转追加到 key的末尾

实例: 主键+“|”+加密后的时间戳

参考: https://www.talkwithtrend.com/Question/432297

4.Hbase 的读写流程 ★★★★

https://segmentfault.com/a/1190000019959411

读:

​ 1.Client 请求ZK 获取 Meta Table 所在的Region Server的地址

​ 2.Client 查询这台管理 meta table 的Region Server,获取本次查询的 rowKey 由哪台Region Server管理。Client会缓存这个信息,以及Meta Table 的位置信息。

​ 3.Client 直接向目标 Region Server 进行访问,先从MemStroe 上读,没有再从StroeFile 上读 获取数据。

写:

​ 1.Client 请求 ZK 获取Meta Table 所在的 Region Server 所在的位置

​ 2.根据 nameSpace 、表名、rowKey、以及meta 表,找到写入数据对应的 Region 信息。

​ 3.找到对应的 Region Server ,把数据先写到 WAL(Wrtie Ahead Log),然后写到 MemStroe。

​ 4.当 MemStroe 达到阈值后,会把数据刷成磁盘上的StroeFile 文件。

​ 5.当多个 StroeFile 文件达到一定大小后,会触发 compact 合并操作,合并为一个 Store File ;而当 这个文件大小超过一定的阈值后,会把当前的 Region 分割为两个,并由 Hmaster 分配给相应的 HRegion Server ,实现负载均衡。

四、Hive

1.Hive 的原理 ★★★★★

1.提交SQL到hive

2.查询元数据

3.生成逻辑计划,优化逻辑计划

4.生成物理计划,优化物理计划

5.执行物理计划

6.封装结果集,返回数据

2.Hive有几种表 ★★★★★

1.内部表:创建时,数据会被移动到数仓指定的目录下;删除时,元数据和数据一并删除

2.外部表:创建时,仅记录数据所在的位置,不进行移动;删除时,只删除元数据,不删除数据

3.分区表:根据表中的某个字段进行分区,类似于文件夹。例如:日志文件,根据时间,每天一个分区

4.分桶表:相比分区表,更加细粒度的划分,根据表中某个字段的hash值进行分割,类似于一个文件拆分为多个文件。

5.临时表:储存在用户的暂存目录中,并在会话结束后进行删除

3.order by 、 sort by 、distribute by 、 cluster by ★★★★

order by :全局排序,只有一个 reduce 耗时长

sort by : 局部有序,不保证多个reduce之间有序,只是单个reduce有序

distribute by: 控制map的分发结果,具有相同字段的map分发到同一个reduce

cluster by: 相当于是 distribute by + sort by 【只能是降序】

4.什么是数据倾斜,怎么解决 ★★★★★

数据倾斜:数据分布不均匀,有的过分多,有的太少,导致处理数据的时候,有的很快,有的特别慢,从而导致任务一直无法完成。

根本原因:key 的分布不均匀。

解决办法:1: 合理设置map数

​ ①.小文件合并:CombineHiveInputFormat

​ ②.复杂文件增加map数:调整切片最大值,maxsize,使其小于 block size

​ 2.: 合理设置 reduce 数

​ ①:set mapreduce.job.reduces= N

​ 3.打乱集中的key,使其进入不同的reduce

5.Hive 调优 ★★★★★

https://blog.csdn.net/qq_43259670/article/details/105927827?spm=1001.2014.3001.5506

hive调优,一般通过 hive-site.xml 或者 客户端配置完成,一般的调优策略有:

①:jvm重用

②:合并block 减少 task 数量

③:开启小文件合并

④:开启数据压缩

⑤:有数据倾斜时进行负载均衡

五、Kafka

1.Kafka采用了那些设计保证高性能 ★★★★★

1.producer : ①磁盘顺序写 ② MMF 内存映射文件

2.consumer: ①zero-copy

2.Kafka的幂等性 ★★★★★

幂等性:一般而言是指,对于同一个资源,一次请求和多次请求的结果对资源本身应该是完全一致的。
(比如电子支付,由于网络延迟或者手机卡顿等原因,超市的收银员扫了你2次收款码,这时候,你的电子钱包应该要做到只被扣除一次,不能多次扣除,而要做到这一点,①要保证订单有唯一的id ②处理端要记录下已经处理过的请求,如果下一条来的id已经存在,则丢弃掉不能处理)

kafka的幂等性是对生产者而言的,具体做法是 kafka对每一条消息添加一个 sequence number,(每条消息对应一个分区,不同分区的消息不会存在重复)而broker会储存这个sequence number,当下一条消息来的时候,只有 sequence number 比上一条的>1,则保留,否则丢弃。

3.消息丢失与消息重复 ★★★★★

消息丢失:

​ produce:
①ack设置了0,导致生产者发送消息后,不确认分区副本是否收到,如果失败,就会丢失。

​ ②ack设置了1,只有leader保存了消息,就返回成功,follower未同步,leader就挂掉。

​ 解决办法: 设置 ack = all

​ consumer:
①自动提交了offset,但是后续业务逻辑未处理完就失败

​ 解决办法:手动提交偏移量,待业务逻辑处理完后提交

消息重复:

​ producer:
①发送一条消息,副本已保存,但是因为网络等多种原因未返回成功,多次重试

​ 解决办法:开启kafka的幂等性

​ consumer:
①消费端在消费过程中挂掉没有及时提交offset,另一个消费端拿取了之前的记录进行消费

​ 解决办法:在下游程序做幂等性

4.几个概念 ★★★★

https://blog.csdn.net/weixin_43230682/article/details/107317839

ISR: 与leader保持同步的follower集合 (In-Sync Replicas)

AR:每个分区下的所有副本统称 (Assigned Replicas)

LEO:每个分区最后一条消息的位置 (log Eed Offset)

HW: 一个分区对应的ISR中最小的LEO作为 HW (High Watermark)

5.Kafka的储存与顺序一致性、如何保证顺序消费 ★★★★★

1.kafka的每一个分区内部是有序的,因此只要保证需要有顺序的数据都向同一个分区写就可以。
​ kafka自身的分区策略:
①用户给定分区号,发送数据到指定分区
​ ②没有给定分区号,但是有Key,根据key取hash进行分区
​ ③ 没Key没分区号,轮询分区
​ ④ 自定义分区

2.一个分区只能对一个消费者使用,因此要保证顺序消费,就要:
①:消费者单线程处理消息
​②:写N个队列,将具有相同Key的消费储存在同一个队列里,对于N个线程,一 个线程消费一个队列即可

六、Spark

1.Spark的工作流程 ★★★★★

1.用户通过 Spark-Submit 提交代码至服务器,创建SparkContext,在SparkContext初始化的时候会创建DAGScheduler 和 TaskScheduler

2.初始化的同时,向ClusterManager注册Application并申请资源

3.ClusterManager 会使用自己的资源调度算法,在集群的worker 节点上,启动多个 Executor

4.Executor 会反向注册给Driver ,结束sparkcontext 的初始化。

5.调用 DAGScheduler 完成任务阶段的划分

6.每一个stage 创建一个 taskset

7.taskScheduler 将 taskset 分发给 executor 进程,完成计算。

2.RDD ★★★★★

弹性分布式数据集,是spark中最基本的数据抽象,它代表一个不可变,可分区,内部元素可并行计算的集合

创建方式:①makeRdd,通过集合创建

​ ②使用外部数据源创建,如HDFS

​ ③通过其他RDD的结果创建

3.算子 ★★★★★

转换算子: map、flatmap、filter、join、repartition、coalsece、distinct 、groupByKey 、reduceByKey

动作算子:collect 、 foreach 、take 、first 、count、 saveAsTextFile

4.RDD的依赖关系 ★★★★★

宽依赖:多个子RDD的分区依赖同一个父RDD的分区
窄依赖:每一个父RDD的分区最多被子RDD的一个分区使用

5.Stage 怎么划分 ★★★★★

根据RDD之间的依赖关系,遇到一个宽依赖就划分一个stage,宽依赖表示数据有shuffle过程,即可以认为遇到数据shuffle就产生一个stage,划分stage有利于形成DAG图,方便在一个stage内达到数据执行效率的最大化,实现流水线计算。

6.stage 、 Job 、 task ★★★★★

job : 遇到一个action 操作,就划分一个job,一个job中包含一个或多个stage

stage:遇到一次shuffle就划分一个stage

task:RDD的有多少的partition就有多少task,是stage中的一个执行单元,一个stage就是一个taskset

7.spark的调优 ★★★★★

1.修改序列化机制,采用 Kryo优化序列化性能

2.提高并行度

​ ①:设置 task的数量

​ ②:repartition ,给rdd重新分区

3.RDD的重用和持久化

4,使用广播变量,广播小数据

5,减少使用会产生shuffle的算子

6.使用高性能的算子

①:如用 reduceByKey 替代 groupByKey

②:用mapPartitiond 替代 map

③:用 foreachPartitions 替代 foreach


转载:https://blog.csdn.net/ASYMUXUE/article/details/115984259
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场