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

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

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的区别?

ArrayList 底层是数组,查询效率高,增删效率低,默认初始长度为10,数组扩容新=1.5*旧,然后把原数组的数据,原封不动的复制到新数组中(用的是 Arrays.copyOf() 方法 ),LinkedList 增删快,底层为双向链表,遍历ArrayList要比LinkedList快,遍历的优势在于内存的连续性,CPU的内部缓存结构会缓存连续的内存片段,可以大幅降低读取内存的性能开销。

3、CMS和G1垃圾收集器的区别?

CMS采用 标记-清理 的算法:

  1. 初始标记:stop the world,仅仅只是标记一下GC Roots能直接关联到的对象,速度很快
  2. 并发标记(耗时最长):进行GC Roots Tracing的过程,收集器线程与用户线程一起工作
  3. 重新标记:stop the world,为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,时间比初始标记阶段稍长一些,但远比并发标记的时间短。
  4. 并发清除(耗时最长):并发回收垃圾,收集器线程与用户线程一起工作

G1:

面向服务端应用的垃圾收集器,整体看基于标记整理算法,局部看基于复制(两个region之间),不会产生内存空间碎片,可预测停顿,能让使用者明确指定在一个长度为N毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,使用G1收集器时,它将整个Java堆划分为多个大小相等的独立区域(Region),新生代和老年代不再是物理隔阂了,它们都是一部分(可以不连续)Region的集合。G1跟踪各个region中垃圾堆积的价值大小(回收空间及所需时间),在后台维护一个优先列表,在每次被允许的时间内,优先回收高价值的。

  1. 初始标记:stop the world,仅仅只是标记一下GC Roots能直接关联到的对象,速度很快
  2. 并发标记:进行GC Roots Tracing的过程(进行可达性分析),可与用户程序并发执行
  3. 最终标记:stop the world,为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,并行执行
  4. 筛选回收:对各个region回收价值和成本排序,制定回收计划。

4、HashMap是线程安全吗?为什么?

非线程安全。

JDK7中:多线程并发put,造成循环链表,get时出现死循环。

多线程执行 put:线程A、B同时put,同时执行到 if ((e = p.next) == null),同时进入下一步,先是 e->A ,然后 e -> B , 而不是 e -> A -> B ,丢失A。

put、get并发时:put触发resize,get得到的可能是null。

5、Java的IO模型?BIO和NIO的区别?

BIO:面向流,是阻塞IO,在读取数据时,用户线程发出IO请求后,内核会检查数据是否就绪,没有就绪的话就继续等待数据就绪,用户线程处于阻塞状态并交出CPU,就绪后,内核将数据拷贝到用户线程,接触阻塞状态。

NIO:同步非阻塞,用户线程发起读请求之后,不需要等待,立刻会得到一个结果,结果是error时,说明数据还没准备好,可以再次发送读请求,一旦数据准备好之后,并且再次收到了读请求,就将数据拷贝到用户线程。

AIO:异步非阻塞,用户发起一个IO之后立即返回,也不用自己去轮询,当IO完成之后,内核会给用户线程发信号,告知IO已完成

6、常见的gc回收器和区别

  1. Serial
  2. ParNew
  3. Parallel
  4. CMS
  5. G1

7、Map有哪几种

  1. HashTable,实现了map接口
  2. HashMap
  3. TreeMap(基于红黑树,有序)
  4. LinkedHashMap(HashMap的基础上加上双向链表,非同步)
  5. ConcurrentHashMap

8、ConcurrentHashMap怎么保证线程安全

底层是基于 数组 + 链表

1.7:由 Segment 数组、HashEntry 组成,采用了分段锁技术,支持 Segment 数组数量的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。

1.8:采用了 CAS (乐观锁)+ synchronized 来保证并发安全性,链表长度>8转为红黑树

9、volatile和sychronized关键字原理

10、hashcode()相同,equals一定相同吗

11、HashTable和HashMap有什么区别

  1. Hashtable 是不允许键或值为 null 的(在put 空值的时候直接抛空指针异常),HashMap 的键值则都可以为 null
  2. Hashtable 继承了 Dictionary类,而 HashMap 继承的是 AbstractMap 类
  3. HashMap 的初始容量为:16,Hashtable 初始容量为:11
  4. HashMap 扩容规则为2倍,Hashtable 扩容规则为2倍 + 1

12、四种引用说一说

  1. 强:存在就不会被回收
  2. 软:第一次回收后,空间还是不够,进行第二次回收,会回收软引用
  3. 弱:第一次就被回收
  4. 虚:对象被回收时收到一个系统通知

13、抽象类与接口的区别

14、JVM虚拟机,为什么需要虚拟机

15、多线程和多进程有什么区别?

16、java有哪些锁

17、JVM的内存模型讲一下。

18、hashmap冲突了怎么处理的?

19、treemap底层是怎么实现的?

20、线程的状态及状态之间的装换

Hive部分

1、Hive有哪些引擎?

MR、Tez

2、udf,udtf 怎么写

继承UDF 类,重写 evaluate 方法

继承 UDTF类,重写process方法,调用forward方法输出数据。(之前用阿里的MaxCompute是继承 UDTF,Hive的实现上可能有区别)

3、hive窗口函数row_number、rank、dense_rank的区别?

  1. row_number:分组排序 ,123345
  2. rank:数据在分组中的排名,排名相等会留下空位,12335
  3. dense_rank:数据在分组中的排名,排名相等不会留下空位,12334

4、Hive里面map和reduce的数量怎么确定?哪些参数可以调控map的数量

map
没有办法直接设置,主要决定因素为:输入文件的数量、大小,集群设置的文件块的大小

-- 决定每个map处理的最大的文件大小
set mapred.max.split.size=100000000;

reduce

-- 设置reduce的数量
set mapred.reduce.tasks = 15;

不指定的话,默认的计算方式为:min(每个任务最大的reduce数,总输入数据量/每个reduce任务处理的数据量)

5、mapjoin 问题?

小表join大表,小表在左边,大表右边,将小表读入内存,在map端join大表,省略reduce

6、cluster by 、sort by、distribute by 、order by 区别

  1. order by:全局排序,所有数据都通过一个reducer进行处理,数据集过大可能极慢
  2. sort by:在每个reducer中进行排序,保证每个reducer的输出有序,但并非全局有序
  3. distribute by:控制map的输出在reducer中如何划分,distribute by year 年份相同的数据都分到一起
  4. cluster by:distribute by year+sort by year asc(升序)的简写方式 = cluster by year

7、left semi join 作用

left semi join(左半开连接):返回左表的记录,其记录对于右表满足on的筛选条件(可替代in)

8、Hive分区分桶的区别

分区:将数据从物理上转移到和使用最频繁的用户更近的地方,分区表改变了hive对数据存储的组织方式,warehouse/数据库/表名 —> warehouse/数据库/表名/dt=2020,分区后hive将创建可以反映分区结构的子目录。

分桶:分桶则是指定分桶表的某一列,让该列数据按照哈希取模的方式随机、均匀地分发到各个桶文件中。因为分桶改变了数据的存储方式,它会把哈希取模相同或者在某一区间的数据行放在同一个桶文件中。提高查询效率(对两张在同一列上进行了分桶操作的表进行JOIN操作的时候,只需要对保存相同列值的桶进行JOIN操作即可)

create table ... cluster by user_id into 96 buckets

插入时需要 set hive.enforce.bucketing=true 强制hive为目标分桶表设置正确的reducer数,如果不指定,需要自己设置正确的reducer数:set mapred.reduce.tasks=96

9、Hive底层原理,sql执行过程

  1. HiveSQL通过SQL Parser,完成SQL词法,语法解析,将SQL转化为抽象语法树(AST)
  2. 遍历AST,进行Analyzer语义分析,抽象出查询的基本组成单元QueryBlock(QB)
  3. 生成逻辑执行计划:遍历QueryBlock,翻译为执行操作树Operator Tree
  4. 优化逻辑执行计划:逻辑层优化器进行OperatorTree变换,合并不必要的操作符,减少shuffle数据量,得到优化后的操作树
  5. 生成物理执行计划:遍历OperatorTree,翻译为MapReduce任务
  6. 优化物理执行计划:物理层优化器进行MapReduce任务的变换,生成最终的执行计划

10、HDFS中的数据怎么写入Hive中

load data inpath ‘文件路径’ into table 对应库表名

数仓部分

1、数仓分层每层是做什么的?

  1. 操作数据层
  2. 数据仓库层(明细数据层、轻度聚合层)
  3. 数据应用层
  4. 维度表
  5. 临时表

2、事实表维度表构建

3、OLAP 与 OLTP 的区别

4、行式数据库和列式数据库区别

Hadoop 部分

1、MapReduce的shuffle机制?

2、mr的combiner主要是做什么?

3、介绍一下MapReduce的过程

4、表A join 表B,讲一下MapReduce是怎样执行的

5、NameNode和DataNode

6、使用Hadoop需要启动哪些进程

7、HDFS读写机制

8、Hadoop序列化和反序列化

9、Hadoop的架构

10、Hadoop作业提交到Yarn流程

11、NodeManage挂掉怎么办,两个任务同时请求资源怎么办

12、Reduce如何获取Map的结果

13、mapreduce shuffle为什么要环形缓冲区

14、HDFS小文件过多会怎么样

  1. 小文件会开很多map,一个map开一个JVM去执行,所以这些任务的初始化,启动,执行会浪费大量的资源,严重影响性能
  2. HDFS中,小文件过多会占用大量内存,NameNode内存容量严重制约了集群的扩展
  3. HDFS读写小文件更加耗时,每次都需要从 NN 获取元信息,并与对应的DataNode建立连接

小文件是如何产生的

  1. 动态分区插入数据,产生大量的小文件
  2. 参数设置的 reduce 数量太多
  3. 数据源本身就包含大量的小文件

小文件的解决方案

  1. 设置合并参数;
  2. 少使用textfile;
  3. 少用动态分区;
  4. 设置reduce数量

对于已有的小文件的解决方案

  1. Hadoop archive命令进行归档;
  2. 重跑数据,指定map reduce参数,指定存储格式(ORC)

数据库部分

1、MySQL的索引?b+树相对于b树有什么优点?

2、MySQL 数据量大怎么办(索引、分库分表知识点)

3、最左匹配原则,ACID

4、覆盖索引

5、MySQL中char和varchar有什么区别?

6、Hash索引和B+Tree索引的区别

7、联合索引是什么

数据结构

1、描述堆排序

2、基数排序过程

3、有哪些树结构

4、B+树的特点

5、排序算法都有哪些

6、栈的push和pop的时间复杂度

7、红黑树特性,红黑树如何实现

计网

1、TCP三次握手四次挥手?

2、TIME-WAIT什么时候发生?持续时间?

3、在不同的网络环境中MSL一样吗?

4、解释最长报文段寿命?

5、udp应用场景

6、dns解析过程,本地在哪缓存,服务器上怎么缓存

7、HTTPS的工作流程

8、网络结构以及每层应用

场景题

1、如何从百亿条IP信息中得出访问量前10的IP地址

2、你自己如何设计一个分布式系统,实现对百亿条数据进行分组并求和

3、在100亿个无符号整数中取最大100个 topK 有内存限制和无内存限制不考虑分布式

Linux

1、linux根目录有哪些文件夹

/sys 存储设备驱动信息

/home,/root,用户主目录

/usr

/etc,配置文件的存放位置

/lib,存放库文件

/bin , 可执行命令

/sbin , 管理员命令

2、查看进程的命令有哪些

ps aux

top

3、如何查找指定关键字的进程信息

通过管道

ps aux | grep xxx

4、怎么知道系统CPU负载高

top命令

Coding

1、实现左旋n位的字符数组?

2、二叉树的广度优先遍历和深度优先遍历

3、sql题,求连续活跃5天的用户

4、实现微信发红包,输入是红包数和总金额,实现随机分配

5、一个数组里面每个元素表示每天的股票价钱,怎么样买入和卖出能赚最多的钱?只能先买入再卖出

6、n个个位数,全排列组成一个整数。怎么找到最近的下一个比他大的数。时间复杂度要求o(n)

7、返回二叉树的镜像,非递归算法。

8、抖音用户浏览视频日志 TableA(date, user_id, video_id), 统计2020.03.29观看视频最多的前5个user_id(相同视频要排重)。

9、leetcode80. 删除排序数组中的重复项 II

10、数组求top k

11、sql题 分组求每组top 3

12、二叉树的后序遍历 非递归实现

13、用spark求一下dau

14、子序列的最大和

15、最小逆序对

16、二叉树层序遍历,按层换行输出。

17、一个数组有正数有负数,调整数组中的数使得正负交替

例:[-3, 6, 7, -4] ->[6, -3, 7, -4]

18、leetcode 字典序的第k小数字

19、网上购物返现,假设你需要购买某一商品,每天都要购买一次,连续买n天,但每天有不同的价格。你知道每天的价格,如果某一天你花8块买了,未来某一天价格降到了1块,就会返现7块,只能返现一次。求连买n天商品的最小价钱。

例如,输入[3,2,1,5],那么总共花了11块,但返现了3元,所以最少花了8块买了4件商品。

20、快排

21、求一个成对数组中,只出现一次的数

22、用两个栈实现栈的排序

23、用两个栈实现队列

24、lc丑数3

25、数据流中的中位数

26、Leecode513. 找树左下角的值,非递归与递归两种方法

27、归并排序

28、两个有序数组间相加和的Topk问题

29、最少票价问题(动态规划求解)

30、二叉树的序列化与反序列化

31、二分查找

32、无重复字符的最长子串

33、大数组求中位数

34、使用spark写一个wordcount

35、两个字符串的最大公共子串

36、信封问题

37、两个二叉树如何判断是不是对称

38、链表翻转

39、N个有序数组,取其中m个最小的数,m远小于N个数组中数的个数,时间复杂度是多少

40、对折链表

41、给定误差范围,计算正浮点数x的平方根,不可以使用幂运算,可以用四则运算。

42、给定数组包含正负数(数量至多差1),要求将其排列成正负彼此相邻形式,要求时间复杂度O(N),空间复杂度O(1)

43、 1-N个数字,找出字典序第K大的数字,要求空间O(1),时间O(K)

举例1-19字典序为1,10,11,12,13,14,15,16,17,18,19,2,3,4,5,6,7,8,9

44、给定一个序列和排序中间结果,判断是插入还是归并排序的中间结果,并输出下一次排序结果。

45、非递归后序遍历

46、二维数组的顺时针打印

47、旋转数组的查找

48、2个有序数组中位数,要求O(logN)

49、判断一颗二叉树的宽度

50、求字符串的最长回文子序列

51、接雨水

52、在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

53、我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

  • 4
    点赞
  • 3
    评论
  • 34
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值