字节抖音大数据开发校招面经总结

本文详细梳理了字节跳动大数据开发面试的常见问题,涵盖Spark、Java、Hive、数据库、数据仓库、Hadoop等多个方面。内容包括Spark的Stage、Executor和Task的作用,数据倾斜的解决策略,以及Spark与MapReduce的速度优势等。还讨论了HashMap、ArrayList、LinkedList的区别,CMS和G1垃圾收集器的差异,以及Hive的窗口函数和分桶的区别。此外,还涉及到数据库的ACID原则、TCP的三次握手和四次挥手、数据流中的中位数计算等计算机网络和数据库基础。
摘要由CSDN通过智能技术生成

翻了一些牛客上的字节面经,对常见面试题做了下总结~

Spark部分

1、Spark中Stage、Executor、Task都是干嘛的?

  1. stage:每个job被划分为多个stage,一个stage中包含一个taskset
  2. task:在executor进程中执行任务的工作单元
  3. Executor:运行在worker节点上的一个进程,负责运行某些task,并将数据存在内存或者磁盘上。
  4. Worker:集群中可以运行Application代码的节点,在Spark on Yarn模式中指的就是NodeManager节点。
  5. Driver:main()函数,创建SparkContext,由SparkContext进行资源申请,任务的分配和监控等。程序执行完毕后关闭SparkContext。

2、Spark 数据倾斜

原理

shuffle时各个task处理的数据量不均匀

如何定位数据倾斜

  1. 只会发生在shuffle过程中,可能会触发shuffle操作的算子:distinct、groupByKey、reduceByKey、aggregateByKey、join、cogroup、repartition等
  2. 在web UI上查看,看日志,在代码第几行溢出,附近的shuffle算子
  3. 查看出现问题的RDD或hive表的key分布状况,用countByKey统计一下

解决方案

  1. 预处理,过滤导致倾斜的key
  2. 提高shuffle的并行度
  3. 将reduce join替换为map join:将小的broadcast广播,在大的里面用map遍历,看key是否相同
  4. 两阶段聚合(局部聚合+全局聚合),打上随机前缀,接着对打上随机数后的数据,执行reduceByKey等聚合操作,再对结果进行全局聚合,去掉前缀
  5. 使用随机前缀和扩容RDD进行join

3、spark为什么比mr快?

  1. shuffle过程中Hadoop需要落硬盘,spark不一定,可以缓存在内存中,IO少
  2. Hadoop的task是一个个进程,spark是一个个线程;
  3. Hadoop容错性低,spark可以根据RDD之间的血缘关系重算;
  4. spark有transform和action算子,只有遇到action才会触发job,会做流水线层面的优化;
  5. 多次使用的RDDspark可以进行缓存

4、Spark的stage的划分是怎么划分的?

在spark中,会根据RDD之间的依赖关系划分DAG图,对于窄依赖,由于partition依赖关系的确定性,可以在同一个线程里完成,窄依赖就被spark划分到同一个stage中。

stage划分思路:从后往前推,遇到宽依赖就断开,划分为一个stage,遇到窄依赖就将这个RDD加入该stage中。

5、介绍一下 Spark RDD、DataFrame、DataSet

  1. RDD:弹性分布式数据集,spark中最基本的数据抽象,不可变,可分区,里面元素可并行计算
  2. DataFrame是一种以RDD为基础的不可变分布式数据集,DataFrame与RDD的主要区别在于,DF带有schema元信息,数据都被组织到有名字的列中,每一列都带有名称和类型
  3. DataSet:和dataFrame差不多,可以把 DataFrame 当作 Dataset[Row] 的别名,每一行的类型是Row;

6、Spark的窄依赖和宽依赖

窄依赖:每个父RDD的一个分片最多被子RDD的一个分片使用。窄依赖以pipeline管道形式顺序执行多条命令,分区内的计算收敛,可以并行地在不同节点进行计算。失败时只需要计算丢失的parent partition

宽依赖:父RDD的分片会被多个子RDD的分片使用。需要所有的父分区都是可用的,失败恢复时,宽依赖牵涉RDD各级的多个parent partition

7、DAG Scheduler作用

接收提交的job的主入口,根据job构建基于stage的DAG,并将每个Stage打包(task的分区信息和方法,并序列化)成TaskSet交给TaskScheduler调度。stage的划分依据是RDD之间的依赖关系。还会处理 task 执行成功 , cancel job , cancel stage 等事件。

8、Spark中有哪些算子会进行shuffle,有哪些不会进行shuffle

***有 shuffle ***
distinct 、 intersection 、 substract 、substractByKey 、join 、lefouterjoin、
reduceByKey 、 group by 、 groupbykey 、 aggregratebykey 、 combinebykey 、
sortby 、 sortbykey 、 coalease 、 repartition

无 shuffle

map 、 flatmap 、 mapPartitions 、 filter

9、union可以形成宽依赖吗?

union 为窄依赖,不会触发 shuffle , 不会划分 stage , 可能会重新分区

10、Spark 作业调度

调度主要通过 DAG scheduler 和 Task Scheduler。

DAGScheduler:接收提交的job的主入口,根据job构建基于stage的DAG,并将每个Stage打包成TaskSet交给TaskScheduler调度。

TaskScheduler :将发来的 taskSet 封装为TaskSetManager加入到调度队列中,TaskSetManager负责监控管理同一个Stage中的Tasks,TaskScheduler就是以TaskSetManager为单元来调度任务。

SchedulerBackend 会定期询问 TaskScheduler 有没有任务要运行,TaskScheduler会从调度队列中按照指定的调度策略(FIFO(默认)、FAIR)选择 TaskSetManager 去调度运行。

11、Spark的提交模式

  1. standalone:基于Spark自己的Master-Worker集群。没用Yarn。
  2. yarn-cluster:driver运行在AM中,当用户提交了作业之后,就可以关掉Client,作业会继续在YARN上运行,不适合运行交互类型的作业。
  3. yarn-client:Client不能离开,Driver在哪提交就在哪

12、yarn-cluster涉及的参数有哪些

executor-memory

spark.driver.memory

spark.driver.maxResultSize

spark.executor.cores

spark.driver.cores

spark.sql.shuffle.partitions

spark.serializer

spark.network.timeout

spark.yarn.executor.memoryOverhead

spark.dynamicAllocation.maxExecutors

13、有关资源分配参数如何自动分配

spark.dynamicAllocation.enabled 资源动态分配

spark.dynamicAllocation.minExecutors 动态最小的executor数量

spark.dynamicAllocation.maxExecutors 动态最大的executor数量

14、Spark shuffle 过程

15、Driver 怎么管理 excutor的

16、cache()算子

17、广播变量介绍一下,什么场景下用广播变量?广播变量和cache区别?

18、Spark的组件有哪些

20、如果要增加并发应该使用什么参数,executor和core的比例怎么设置

21、Spark join的几种实现方式

总体上来说,Join的基本实现为,Spark将参与Join的两张表抽象为流式遍历表(streamIter)和查找表(buildIter),通常streamIter为大表,buildIter为小表,spark会基于streamIter来遍历,每次取出streamIter中的一条记录rowA,根据Join条件计算keyA,然后根据该 keyA 去 buildIter 中查找所有满足Join条件(keyB==keyA)的记录 rowBs,并将rowBs中每条记录分别与 rowA join得到 join 后的记录。

sort merge join:分别对 streamIter 和 buildIter 进行排序,在遍历streamIter时,对于每条记录,都采用顺序查找的方式从 buildIter 查找对应的记录,每次处理完 streamIter 的一条记录后,对于streamIter的下一条记录,只需从 buildIter 中上一次查找结束的位置开始查找,不必从头找。

broadcast join:如果 buildIter 是一个非常小的表,直接将buildIter广播到每个计算节点,直接在一个map中完成 join,也叫map join。

hash join:将来自buildIter的记录放到 hash表 中,加快查找

22、map算子和flatMap

map:将一个RDD中的每个数据项,通过map中的函数映射变为一个新的元素,有多少个输入分区,就有多少个输出分区

flatmap:Transformation算子,第一步和map一样,最后将所有的输出分区合并成一个分区,flatMap会将字符串看成是一个字符数组,并不会把Array[String]也扁平化成字符数组

23、Hive和Spark区别

Java部分

1、HashMap的实现?为什么要转化为红黑树?为什么大于8才转换?

实现

由数组和链表组合构成(可以从1.7、1.8展开详细讲)

为什么要转化为红黑树

链表是取一个数需要遍历链表,复杂度为O(N),而红黑树为O(logN)

为什么大于8才转换

哈希表中节点的频率遵循泊松分布,根据统计,列表长度为8的时候期望就已经很小了,没必要再往后调整。(源码中注释部分有具体解释)

2、ArrayList和LinkedList的区别?

A

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值