面试题01

面试题

1. java

  1. 多线程的常用创建方式有几种?分别是什么?
    继承Thread类, 直接new MyThread (Thread类也是实现了runnable接口)
    直接实现runnable接口 重写run方法

  2. ArrayList、HashSet、HashMap的底层实现
    ArrayList底层其实是创建了一个数组。 grow 为扩容 线程不安全

  3. GC算法
    引用计数, 根搜索算法
    - 复制 : 从根集合开始扫描,将存活得对象移动到另一块空闲得区域。
    - 标记 清除 :从根集合开始扫描,存活得进行标记,再扫描整个空间,未被标记得清除,扫描耗时
    - 标记 压缩 : 与标记清除类似,再加上整理碎片,进行移动

2. Hive

  1. Hive分桶
	提高join效率

	hive分桶是根据分桶表的分桶字段的hash值将数据放入不同的桶内
	因为mapreduce的分区算法,根据id的hashcode值模上reducetasknumber,
	所以一个id分到同一个桶里,浙江合并不需要整个表便利笛卡尔积,对应的桶合并
  1. hive实现原理
hive解析SQL字符串,解析成抽象语法树ASK
和元数据进行关联,确定语法能不能过得去
再到逻辑执行计划,对其进行优化(列裁剪等等)
再到物理执行计划
再到优化过后得物理执行计划
  1. Hive转MR过程
    在这里插入图片描述

  2. hive数据倾斜调优

原因:
a group by 导致的数据倾斜
b join导致的数据倾斜


解决方式
a. 采用给null值一个随机数,把倾斜数据分到了多个reduce上
b. 设置reduce的 并行度,如果并行度太少,一个reduce内数据太多,可以设置多个reduce,分担每个reduce处理的数据量
c. 对倾斜的key打上随机值,分发到不同的reduce
d. 小表join大表 	select /*+ mapjoin(t2)*/ column from table ,将reduce join 转为 map join
e. 过滤大key值,单独join
  1. Hive优化
a 数据集小可以用本地执行
b 不是所有聚合操作都要再reduce完成,很多聚合操作都可以再map部分聚合,最后再reduce得到结果
c hive.groupby,skewindata= true 负载均衡
d 慎用api 数据量大时慎用count(distinct) 
f 合理设置map reduce task 个数
  1. hive 内外表区别
删除内部表会直接删除元数据(metadata)及存储数据;(默认创建)
删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除;
  1. sort by 和 order by
order by全局排序 只有一个reducer
sort by在数据在reducer之前排序,保证每个reducer输出有序,全局不能保证
  1. 介绍一下 hive 得map join
		1. hive common join
				若不指定map join或者达不到条件, hive自动解析为common join
				三个阶段: 
				map
					- map输出以join条件中得列为key, 如果join多个字段,则这些关联键为key
					- map输出得value为join之后 select 或者 where 中用到得列 
					- 按照key进行排序
				shuffle
					按照 key得hash值推送到不同reduce中,确保两个表中相同key位于同一个reduce中
				reduce
					按照key完成join操作
		2. hive map join
				大表 join 小表
				由 hive.mapjoin.smalltable.fillsize来确定,默认25M,如果join表中小表小于该值,自动转为map join
				hive0.9之前需要指定,后来只要hive.auto.convert.join=true 就会转为map join
				执行流程如下:
					一个 local task,负责扫描小表数据,将小标转换成hashtable得数据结构,并写入本地得文件中,之后将该文件加载到DistributeCache中,该hashtable得数据结构抽象为:
					|key| value| 
					| 1 | 26 | 
					| 2 | 34 |
				之后执行task B,该任务是一个没有Reduce 得MR,启动maptask扫描大表A,在Map阶段根据a得每一条记录和distributeCache中得对应得hashtable关联,输出结果
				由于没有reduce,map直接输出文件,有几个maptask 就有几个文件输出
  1. UDF UDAF UDTF
		UDF : user defined function
		UDAF: user defined Aggregation Function
		UDTF:user defined Table-generation Function
  1. Rank 窗口函数说明
		RANK(): 相同排名的数据会有相同的排名。但是排名的总数不会减少
		DENSE_RANK():相同排名的数据会有相同的排名,但是排名的总数会减少
		ROW_NUMBER():按顺序排序

3. spark

  1. repartition和coalesce
coalesce()方法的参数shuffle默认设置为false, 多变少
repartition()方法就是coalesce()方法shuffle为true的情况。少变多
  1. Mr和spark得区别
io区别,mr的map数据会落磁盘,reduce读取数据时会有io,spark的map数据会落入内存,减少io,适合迭代
spark Job中间输出可以存在内存中,提高速度
MR是基于进程,spark是基于线程
Spark的多个task跑在同一个进程上,这个进程会伴随spark应用程序的整个生命周期,即使没有作业进行,进程也是存在的
MR的每一个task都是一个进程,当task完成时,进程也会结束

Spark框架和生态更为复杂,首先由RDD、血缘lineage、执行时的有向无环图DAG、stage划分等等,

很多时候spark作业都需要根据不同的业务场景的需要进行调优,以达到性能要求,MR框架及其生态相对较为简单,对性能的要求也相对较弱,但是运行较为稳定,适合长期后台运行


  1. cache 和 persist
		cache 调用无参得persist
		persist 默认memory_only
  1. spark 执行流程
client 提交作业,Driver运行main生成sparkcontext 上下文,执行RDD算子,dagschedule 划分dag图,根据rdd依赖关系划分stage输入task scheduler , task scheduler将stage划分成task 分发给各个节点得executor执行
  1. spark 宽窄依赖
		宽依赖: 父rdd得一个分区被子rdd得多个或一个分区使用
		窄依赖:父rdd得一个分区只被子rdd得一个分区使用
  1. rdd 和 dataframe区别
    在这里插入图片描述
  2. spark 调优
	 spark 开发原则: RDD lineage设计,算子合理使用、特殊操作的优化
	 1. 使用一个写高性能算子
			用foreachpartition 代替 foreach
			mappartition代替map
			filter之后进行coalesce --- 将RDD得数据压缩到更少得partition中去
			使用repartitionAndSortWithinPartitions代替repartition与sort擦偶哦
			
	 3. 避免使用同一个数据集去创建不同的RDD (关系到Lineage) 导致spark进行多次重复计算来创建多个代表相同数据的rdd
	 4. 尽可能复用RDD  减少RDD数量,从而尽可能减少算子执行次数
	 5. 为保证RDD被仅仅计算一次,对多次使用的RDD进行持久化,因为每对一个RDD执行一个算子操作,都会重新从源头算一遍,性能差。
	 6. 尽量避免使用shuffle算子
			reduceByKey、join、distinct、repartition,尽量使用map类非shuffle算子			
	 7. 使用Map-side预聚合得shuffle操作
			建议使用reduceByKey,或者aggregateByKey算子代替groupByKey算子,他们会使用用户自定义得函数对每个节点本地得相同Key进行预聚合
	8. 广播大变量
	9. 设置参数
		num-executors 》 非常重要,如果不设置,只会启用很少得executor, 每个spark 一般50 到100个比价耦合是
		executor-memory 》每个executor内存 4-8G 合适 ,如果有其他得资源队列, 那么申请不超过资源队列最大内存得1/3 - 1/2
		executor-cores 》 executor进程得core数量 决定executor执行task得线程能力 2-4 合适
		driver-memory 》 通常不设置,默认1G
		spark.default.parallelism 》 设置每个stage中task数量500-1000个合适 ,默认是hdfs block 对应一个task。试着参数为 num-executor*executor-cores 得2-3倍
		spark.storage.memortFraction 》设置RDD持久化数据在executor内存中占用得比例 默认0.6 即 executor 60%得内存用来持久化RDD,可以适当提高,保证持久化得数据能够容纳在内存中。如果shuffle多,持久化少,可以降低。如果频繁GC 可以适当降低
		spark.shuffle.memoryFraction 》 设置shuffle过程中一个task拉取上个stage得task输出后,进行聚合操作能够使用得executor内存比例,默认0.2, 就是只有executor内存得20%可以用用于执行该操作。如果使用内存超过限制,多余数据就会溢写到磁盘中取,极大降低性能
  1. spark 数据倾斜
		大部分情况是某几个task得时间过长,就是shuffle时某个key对应得数据量非常打,导致数据倾斜

		如何解决:
				定位: yarn-client 可以定位第几个stage, yarn-cluster web ui定位第几个stage
				1. 过滤掉倾斜得key 》 限制,key太多怎么办
				2. 提高shuffle操作得并行度 》 设置reduceByKey(1000) 即shuffle read task 数量为1000
						原理,原本分配给一个task得多个key 分配给多个task,从而让每个task处理更少得数据
						缺点:只是缓解
				3. 给Key打上随机数, 局部聚合之后将key得后缀去掉,再全局聚合
						缺点:仅仅使用于聚合类得shuffle
				4. reduce join 转为map join, 采用广播小RDD全量数据+map算子来实现与join相同得效果,为map join 不会发生shuffle,适用于小表join大表
				5. 采样倾斜key并分拆join 操作
					对两个大表A 和 B 都进行 大数量Key得 拆分操作,A形成两个RDD, B形成两个RDD,key量大得A进行添加随机数0-n,key量大得B进行膨胀n倍操作。 join之后union操作
				6. 5得基础上,倾斜key很多, 那么A表全部打上随机值,B表全部扩容

4. 校招面

  1. 有 10个文件,每个文件1G ,每个文件得每一行存放得都是用户得query,每个文件得query都可以重复,按照 query 的频度排序

还是典型的TOP K算法,解决方案如下: 方案1: 顺序读取10个文件,按照hash(query)%10的结果将query写入到另外10个文件(记为)中。这样新生成的文件每个的大小大约也1G(假设hash函数是随机的)。 找一台内存在2G左右的机器,依次对用hash_map(query, query_count)来统计每个query出现的次数。利用快速/堆/归并排序按照出现次数进行排序。将排序好的query和对应的query_cout输出到文件中。这样得到了10个排好序的文件(记为)。  对这10个文件进行归并排序(内排序与外排序相结合)。

方案2: 一般query的总量是有限的,只是重复的次数比较多而已,可能对于所有的query,一次性就可以加入到内存了。这样,我们就可以采用trie树/hash_map等直接来统计每个query出现的次数,然后按出现次数做快速/堆/归并排序就可以了

方案3: 与方案1类似,但在做完hash,分成多个文件后,可以交给多个文件来处理,采用分布式的架构来处理(比如MapReduce),最后再进行合并。

  1. 有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词.

对每个词X,采用hash(x)%5000, 但后存到5000个文件中。 每个文件 1G / 5000 = 200K
如果里面有文件大于1M,继续上面不走,知道分解到小文件小于1M。对每个文件,统计每个文件中出现的词以及相应的频率,可以采用trie树,hash_map,并去除出现频率最大的100个词,并把100个词及相应的频率存入文件,这样得到5000个文件。下一步就是把5000个文件进行归并。

  1. 一个client,2个server,动态加入一台机器,或者删除一台机器,或者机器宕机,client如何感知

关键点,心跳,心跳超时了,说明挂了

5. Zookeeper

6. Hadoop

6.1 Hadoop HA

  1. secondary namenode 工作机制
    secondary namenode 请求执行checkpoint
    namenode 滚动正在写的edits日志
    将滚动前得edits日志和fsimage文件拷贝到secondary namnode
    随后secondary namenode 将edits和fsimage加载到内存并合并
    生成新得镜像文件fsimage.checkpoint返回给namenode
    namenode将fsimage.checkpoint重新设置胃fsimage
    所以如果namenode元数据丢失,可与从secondarynamenode恢复一部分元数据信息,如果namenode正在写的edite没有拷贝,那么恢复不了

  2. 如何保证namenode数据存储安全,即 secondary namenode 无法恢复namenode得所有数据
    1. 元数据得共享存储,写入文件时,需要将日志写入共享存储重,写入操作才能认定文件写入成功。然后备份节点才能共享存储同步日志。
    2. ZK监控NN状态,两个NN状态存放在ZK中,另外两个NN节点分别有一个进程监控程序,ZKFC,实时读取ZK中得NN状态,当standeby nn得zkfc发现nn挂了,会强制下线NN,让standby nn切换
    3. 共享存储采用 QJM 即 journal manager。设置一个journal node得集群,主要用来保存edits log。fsimage保存在nn得磁盘上,由journal node合成得集群来存储edits log信息,namenode不仅向磁盘写入edit log,也向journal node集群发送一个写请求,只有当大部分得jn认定写入成功,才写入成功

  3. Map task工作机制
    1. inputformat将文件通过getSplits方法切割成block,多少个block对应多少个map task
    2. 通过recorderReader对象进行读取,返回key value
    3. 用户重写map函数,block进入mapper函数,recorderReader读取一行调用一次
    4. Mapper结束,通过context.write进行collect收集,在collect中,进行hashpartition分区
    5. 数据写入环形缓冲区,达到80后,对key排序,溢写到磁盘
    6. 合并溢写文件

  4. reduce task 工作机制
    1. copy 简单拉取
    2. merge:3种形式: 内存到内存 内存到磁盘 磁盘到磁盘 ,内存数据量达到阈值,启动内存到磁盘得merge,map端没有数据之后,启动磁盘到磁盘得merge,生成最终文件
    3. 合并排序:把分散得数据继合成一个数据,再对合并后得数据进行排序
    4. 调用reduce方法,结果写入HDFS

  5. MRshuffle 和 spark shuffle 区别
    MR基于合并排序思想,在数据进入reduce前进行sort,为了方便后续得reduce端得全局怕徐,spark得shuffle是可选择聚合
    spark内存级得数据转换,不落盘,没有明确得划分
    MR得reduce直接拉去map端数据,spark是靠索引读取,只有action才拉去

  6. yarn 运行流程
    1. 用户向yarn提交作业
    2. resourcemanager 在一个nodemanager上启动一个container, 在container中启动一个application master,application master向resource manager 注册
    3. application master 向resource manager 申请资源
    4. 申请资源后 application master 申请到container
    5. nodemanager 将执行任务所需得启动任务资源,将命令写入脚本启动
    6. 任务向application master反馈状态和进度
    7. applicationmaster 向resourcemanager通信,关闭任务

7. Kafka

  1. kafka 为什么速度快
    写快?
    - 使用pageCache 的 页面缓存
    - 使用 磁盘的顺序写入
    -
    读快?
    - 按照offset有序读
    - pageCache 零拷贝
    - 构建index 索引
    - 构建segement文件段

  2. kafka如何保证不丢数据
    1. 生产者不丢数据
    producer ack
    0:producer不等broker同步完成确认,继续发送信息
    1:producer等leader确认,发送信息
    -1:producer等follower确认,发送信息
    同步 建议 -1
    异步 有buffer 有时间阈值和数量阈值, -1 得话可能会永久阻塞,看情况而定
    2. 消费者不丢数据
    topic有offset,只要不设置相同groupid,就不会混乱消费数据
    3. broker不丢数据
    副本保证不会丢数据

  3. 采集数据什么时候用flume 什么时候用kafka
    数据被多系统消费 用kafka
    数据设计被hadoop使用用flume

  4. 为什么kafka不支持读写分离
    数据一致性问题, 主写从读之间有时间差 可能主数据更新 但是从读出来得数据不一致
    主写主读优点
    1. 简单代码实现逻辑
    2. 没有延时影响
    3. 副本稳定 不会出现数据不一致
    4. 负载能力好 用户可控

  5. kafka 零拷贝
    传统数据发送
    1. 操作系统将数据发送到内核空间页面缓存
    2. 应用程序将页面缓存读取过来放入用户空间缓存
    3. 应用程序将用户空间缓存数据放入内核空间socket缓冲区
    4. 操作系统将scoket缓冲区内得数据发送给网卡

     这里kafka直接省略掉应用程序得步骤 ,将页面缓存直接传入到网洛中
    
  6. kafka isr 机制
    kafka 每个topic 中都有分区和副本
    每个副本都分为leader 和 follower
    follower主动拉去leader得数据进行同步
    注意: kafka 得读写只和leader 得数据有关,follower拉取数据于kafka读写能力无关
    所有 isr 其实就是 kafka 得副本列表
    如何 确定副本在isr列表当中呢?
    1. 首先设置同步时间参数: 副本与leader得同步时间,大于某一参数,剔除
    2. 设置数据消息条数统一: 副本与leader得数据总量,大于某一参数,剔除
    kafka主要通过isr和ack机制保证数据一致和幂等性

8. HBase

  1. hbase怎么写
    client 先写 memstore, 写满之后刷到storefile,storefile达到合并得阈值,进行compact合并操作,storefile合并成一个大的storefile,当单个storefile达到分裂得阈值时,出发split操作,当前region分裂成两个region,老region下线,新分裂出得两个region会被HMaster分配到HregionServer上,实现分流

  2. HBase 为什么支持快速查询
    1. HBase 根据 rowkey查询,只要可以快速定位rowkey,就可以实现快速查询
    2. HBase可划分多个region,理解成关系型数据库得多个分区
    3. 键是排好序得
    4. 按列存储得

  3. Hbase 列簇对应HFile
    1:1 一个列簇对应要给HFile

  4. HBase 写入流程
    1. 获取元数据
    - 先访问ZK, 获取到Meta所在的regionserver
    - 读取meta表的数据, 获取到所有表的元数据
    2. 找到要写的Region
    - 根据meta表的数据确定写入的 region
    - 根据region的 rowkey范围确定 要请求的regionserver
    - 根据regionserver的地址确定 邀请求的regionserver
    3. 写入数据
    - 请求regionserver 写入对应的region
    - 根据列簇确当要写入的store
    - 先写Hlog
    - 再写store 的memorystore

9. SparkStreaming

  1. spark streaming 消费kafka 数据
    方式一: Receivers
    使用Receivers来接受数据,不好得点在于服务器宕机会导致数据丢失。
    为了保证数据不丢失,可以使用WAL日志,就是将接收到得数据保存在WAL日志中(wal日志可以保存在HDFS上)
    失败时从WAL日志中恢复
    方式二:Direct no receivers
    定期从kafka得topic和partition中读取偏移量,根据偏移量范围在每个批处理时间间隔里处理数据。
    1. 简单并行: ss创建与kafka分区相对应得RDD分区数,并行读取数据。
    2. 高效:WAL导致数据被拷贝两份,kafka自身也会复制一份,Direct不需要拷贝数据
    3. 恰好一次: 老版使用Zookeeper保存offset,即高级API。 如果使用kafka低级API , SS保存offset在checkPoint当中。消除SS与zk偏移量不同得情况。

  2. sparkstrming flink storm区别

storm 至少一次 不支持exactly once , 不支持批处理, 对每条数据进行ack,开销大,对吞吐量影响大
sparkstrming 精确一次 。通过rdd来维护状态,开销大,对吞吐量的影响大
flink 精确一次,容错机制较为轻量,对吞吐量影响小,可以达到很大的吞吐量

Flink 是标准的实时处理引擎,基于事件驱动。Spark Streaming 是微批(Micro-Batch)的模型。
时间机制:Spark Streaming 支持的时间机制有限,只支持处理时间。 Flink 支持了流处理程序在时间上的三个定义:处理时间、事件时间、注入时间。同时也支持 watermark 机制来处理滞后数据。
容错机制对于 Spark Streaming 任务,我们可以设置 checkpoint,然后假如发生故障并重启,我们可以从上次 checkpoint 之处恢复,但是这个行为只能使得数据不丢失,可能会重复处理,不能做到恰好一次处理语义。Flink 则使用两阶段提交协议来解决这个问题。

10. scala

  1. scala 伴生对象
    如果有同样一个类与该object名字一样,则称该object为该类的伴生对象,相对应,该类为object的伴生类
    满足没有static,内存共享,节约内存
    object对象为静态常量、静态变量区域,可以直接调用,共享全局变量很有意义,伴生对象方便类的构建,可做为当前类的静态方法、成员的集合。
  2. scala 模式匹配
    match
    不仅可以匹配值,也可以匹配类型, 而且返回值可以自己定义 不管是unit 或是string 或是int都可以
    其实if else 是 parttern match 里面一个典型得类型而已
    作用:使代码更易于测试,易于理解
  3. scala 隐式转换
    即指的是implicit关键字申明得带有单个参数得函数,这样得函数会被自动应用,将值从一个类型转换到另个类型
    隐式转换提供另一种途径告诉编译器将当前类型转换成预期类型
    两种:
    implit def类型
    隐式类
    注意:
    隐士类真的主构造函数只能有一个参数,且这个参数得类型就是要被转换得目标类型

11. mysql

  1. 索引
    作用: 避免全表查找 B+树
    什么字段要作为索引: 频繁查找、频繁关联、分组字段
    为什么索引使用B+树:
    • 因为b+树是把数据都存放在叶子节点中的(在innodb存储引擎中一个b+树的节点是 一页(16k)),那么在固定大小的容量中 B+树的非叶子节点中就可以存放更多的索引列数据,也就意味着B+树的非叶子节点存储的数据的范围就会更大,那么树的层次就会更少,IO次数也就会更少
    • b+树的叶子节点维护了一个双向链表,它更有利于范围查询
    • b+树中的叶子节点和非叶子节点的数据都是分开存储的,分别存放在叶子节点段和非叶子节点段,那么进行全表扫描的时候,就可以不用再扫描非叶子节点的数据了,并且这是一个顺序读取数据的过程(顺序读比随机读的速度要快很多很多),扫描的速度也会大大提高;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值