字节跳动
14、RDD的数据结构是怎么样的?
一个RDD对象,包含如下5个核心属性。
1)一个分区列表,每个分区里是RDD的部分数据(或称数据块)。
2)一个依赖列表,存储依赖的其他RDD。
3)一个名为compute的计算函数,用于计算RDD各分区的值。
4)分区器(可选),用于键/值类型的RDD,比如某个RDD是按散列来分区。
5)计算各分区时优先的位置列表(可选),比如从HDFS上的文件生成RDD时,RDD分区的位置优先选择数据所在的节点,这样可以避免数据移动带来的开销。
13、Spark sql为什么比hive快呢?
计算引擎不一样,一个是spark计算模型,一个是mapreudce计算模型
2、spark和Mapreduce快? 为什么快呢? 快在哪里呢?
Spark更加快的主要原因有几点:
1)基于内存计算,减少低效的磁盘交互;
2)高效的调度算法,基于DAG;
3)容错机制Lingage,主要是DAG和Lianage,即使spark不使用内存技术,也大大快于mapreduce。
3、spark.default.parallelism这个参数有什么意义,实际生产中如何设置?
1)参数用于设置每个stage的默认task数量。这个参数极为重要,如果不设置可能会直接影响你的Spark作业性能;
2)很多人都不会设置这个参数,会使得集群非常低效,你的cpu,内存再多,如果task始终为1,那也是浪费,
spark官网建议task个数为CPU的核数*executor的个数的2~3倍。
2、 conslidate是如何优化Hash shuffle时在map端产生的小文件?
1)conslidate为了解决Hash Shuffle同时打开过多文件导致Writer handler内存使用过大以及产生过多文件导致大量的随机读写带来的低效磁盘IO;
2)conslidate根据CPU的个数来决定每个task shuffle map端产生多少个文件,假设原来有10个task,100个reduce,每个CPU有10个CPU,那么
使用hash shuffle会产生10100=1000个文件,conslidate产生1010=100个文件
注意:conslidate部分减少了文件和文件句柄,并行读很高的情况下(task很多时)还是会很多文件
1、Spark中的HashShufle的有哪些不足?
1)shuffle产生海量的小文件在磁盘上,此时会产生大量耗时的、低效的IO操作;
2)容易导致内存不够用,由于内存需要保存海量的文件操作句柄和临时缓存信息,如果数据处理规模比较大的话,容易出现OOM;
3)容易出现数据倾斜,导致OOM。
14、RangePartitioner分区的原理?
RangePartitioner分区则尽量保证每个分区中数据量的均匀,而且分区与分区之间是有序的,也就是说一个分区中的元素肯定都是比另一个分区内的元素小
或者大;但是分区内的元素是不能保证顺序的。简单的说就是将一定范围内的数映射到某一个分区内。其原理是水塘抽样。
13、spark hashParitioner的弊端是什么?
HashPartitioner分区的原理很简单,对于给定的key,计算其hashCode,并除于分区的个数取余,如果余数小于0,则用余数+分区的个数,最后返回的值就是
这个key所属的分区ID;弊端是数据不均匀,容易导致数据倾斜,极端情况下某几个分区会拥有rdd的所有数据。
12、Spark累加器有哪些特点?
1)累加器在全局唯一的,只增不减,记录全局集群的唯一状态;
2)在exe中修改它,在driver读取;
3)executor级别共享的,广播变量是task级别的共享两个application不可以共享累加器,但是同一个app不同的job可以共享。
10、列出你所知道的调度器,说明其工作原理?
1)FiFo schedular 默认的调度器 先进先出
2)Capacity schedular 计算能力调度器 选择占用内存小 优先级高的
3)Fair schedular 调度器 公平调度器 所有job 占用相同资源
9、一个task的map数量由谁来决定?
一般情况下,在输入源是文件的时候,一个task的map数量由splitSize来决定的,那么splitSize是由以下几个来决定的
goalSize = totalSize / mapred.map.tasks
inSize = max {mapred.min.split.size, minSplitSize}
splitSize = max (minSize, min(goalSize, dfs.block.size))
一个task的reduce数量,由partition决定。
4、不启动Spark集群Master和work服务,可不可以运行Spark程序?
可以,只要资源管理器第三方管理就可以,如由yarn管理,spark集群不启动也可以使用spark;spark集群启动的是work和master,这个其实就是资源管理框架,
yarn中的resourceManager相当于master,NodeManager相当于worker,做计算是Executor,和spark集群的work和manager可以没关系,归根接底还是JVM的运行,
只要所在的JVM上安装了spark就可以
3、提交任务时,如何指定Spark Application的运行模式?
1)cluster模式:./spark-submit --class xx.xx.xx --master yarn --deploy-mode cluster xx.jar
2)client模式:./spark-submit --class xx.xx.xx --master yarn --deploy-mode client xx.jar
1、为什么要进行序列化序列化?
可以减少数据的体积,减少存储空间,高效存储和传输数据,不好的是使用的时候要反序列化,非常消耗CPU。
18、 cache后面能不能接其他算子,它是不是action操作?
cache可以接其他算子,但是接了算子之后,起不到缓存应有的效果,因为会重新触发cache。
cache不是action操作。
10、Spark on Mesos中,什么是的粗粒度分配,什么是细粒度分配,各自的优点和缺点是什么?
1)粗粒度:启动时就分配好资源, 程序启动,后续具体使用就使用分配好的资源,不需要再分配资源;优点:作业特别多时,资源复用率高,适合粗粒度;
缺点:容易资源浪费,假如一个job有1000个task,完成了999个,还有一个没完成,那么使用粗粒度,999个资源就会闲置在那里,资源浪费。
2)细粒度分配:用资源的时候分配,用完了就立即回收资源,启动会麻烦一点,启动一次分配一次,会比较麻烦。
9、map与flatMap的区别?
map:对RDD每个元素转换,文件中的每一行数据返回一个数组对象。
flatMap:对RDD每个元素转换,然后再扁平化。
将所有的对象合并为一个对象,文件中的所有行数据仅返回一个数组对象,会抛弃值为null的值。
7、collect功能是什么,其底层是怎么实现的?
driver通过collect把集群中各个节点的内容收集过来汇总成结果,collect返回结果是Array类型的,collect把各个节点上的数据抓过来,
抓过来数据是Array型,collect对Array抓过来的结果进行合并,合并后Array中只有一个元素,是tuple类型(KV类型的)的。
6、Spark如何处理不能被序列化的对象?
将不能序列化的内容封装成object。
20、Sort-based shuffle的缺陷? (☆☆☆☆☆)
1)如果mapper中task的数量过大,依旧会产生很多小文件,此时在shuffle传递数据的过程中reducer段,reduce会需要同时大量的记录进行反序列化,导致大量的内存消耗和GC的巨大负担,造成系统缓慢甚至崩溃。
2)如果需要在分片内也进行排序,此时需要进行mapper段和reducer段的两次排序。
17、介绍parition和block有什么关联关系?(☆☆☆☆☆)
1)hdfs中的block是分布式存储的最小单元,等分,可设置冗余,这样设计有一部分磁盘空间的浪费,但是整齐的block大小,便于快速找到、读取对应的内容;
2)Spark中的partion是弹性分布式数据集RDD的最小单元,RDD是由分布在各个节点上的partion组成的。partion是指的spark在计算过程中,生成的数据在计算空间内最小单元,同一份数据(RDD)的partion大小不一,数量不定,是根据application里的算子和最初读入的数据分块数量决定;
3)block位于存储空间、partion位于计算空间,block的大小是固定的、partion大小是不固定的,是从2个不同的角度去看数据。
5、谈谈你对container的理解?(☆☆☆☆☆)
1)Container作为资源分配和调度的基本单位,其中封装了的资源如内存,CPU,磁盘,网络带宽等。 目前yarn仅仅封装内存和CPU
2)Container由ApplicationMaster向ResourceManager申请的,由ResouceManager中的资源调度器异步分配给ApplicationMaster
3)Container的运行是由ApplicationMaster向资源所在的NodeManager发起的,Container运行时需提供内部执行的任务命令
14、Spark on Yarn 模式有哪些优点?(☆☆☆☆☆)
1)与其他计算框架共享集群资源(Spark框架与MapReduce框架同时运行,如果不用Yarn进行资源分配,MapReduce分到的内存资源会很少,效率低下);资源按需分配,进而提高集群资源利用等。
2)相较于Spark自带的Standalone模式,Yarn的资源分配更加细致。
3)Application部署简化,例如Spark,Storm等多种框架的应用由客户端提交后,由Yarn负责资源的管理和调度,利用Container作为资源隔离的单位,以它为单位去使用内存,cpu等。
4)Yarn通过队列的方式,管理同时运行在Yarn集群中的多个服务,可根据不同类型的应用程序负载情况,调整对应的资源使用量,实现资源弹性管理
10、 Spark的数据本地性有哪几种?(☆☆☆☆☆)
Spark中的数据本地性有三种:
1)PROCESS_LOCAL是指读取缓存在本地节点的数据
2)NODE_LOCAL是指读取本地节点硬盘数据
3)ANY是指读取非本地节点数据
通常读取数据PROCESS_LOCAL>NODE_LOCAL>ANY,尽量使数据以PROCESS_LOCAL或NODE_LOCAL方式读取。其中PROCESS_LOCAL还和cache有关,如果RDD经常用的话将该RDD cache到内存中,注意,由于cache是lazy的,所以必须通过一个action的触发,才能真正的将该RDD cache到内存中。
6、数据本地性是在哪个环节确定的?(☆☆☆☆☆)
具体的task运行在那他机器上,dag划分stage的时候确定的
1. MapReduce的map个数和reduce个数是怎么确定的
(1) map个数:
split size = max(minSize,min(blockSize,maxSize)),一般情况下,map_num=file_size/blockSize,相当于task的个数
(2) reduce个数:
默认情况下,reduce有两个参数:
hive.exec.reducers.bytes.per.reducer --每个reduce处理的数据量
hive.exec.reducers.max --每个任务最大的reduce数量
reduce_num = min(hive.exec.reducers.max,total_size/hive.exec.reducers.bytes.per.reducer)
手动设置reduce个数:
set mapred.reduce.tasks = n
1. MapReduce和Spark的Shuffle有哪些区别
MapReduce的shuffle过程中每个MapTask拉取数据后写入缓存中,在溢写小文件前进行分区和排序,溢写后的小文件也会进行合并和排序,并且可以选择性进行规约操作,最后每个MapTask生成一个有序的大文件
Spark的shuffle过程中,会按照设置和场景进行不同的shuffle机制,主要有是否分区、是否排序和是否进行小文件合并等区别。
2. Hive调优如何定位问题、排查思路
Hive需要调优一般都是在性能到瓶颈的时候,例如hive脚本执行日志报错、执行缓慢卡在某个stage99%无法继续、任务执行很慢
(1) 日志报错:一般会有return2或者Container killed by the ApplicationMaster容器被杀掉等情况
查看yarn日志信息,一般是reduce数据量过大,导致任务超时,GC的时候Stop the World,默认连接600s
如果某个reduce任务量过大即数据倾斜的情况,explain该sql定位其对应的stage逻辑,针对性处理sql中的处理逻辑,一般为关联表有重复值导致数据翻倍,或者关联表字段有空值导致,对表进行异常值空值的数据过滤、去重处理、关联字段加盐、两表mapsideJoin等操作解决数据倾斜问题
(2) 任务卡在某个stage到99%:
查看该stage的yarn是否存在某个reduce任务数据量大的情况,explain该sql定位其对应的stage逻辑,针对性处理sql中的处理逻辑,一般为关联表有重复值导致数据翻倍,或者关联表字段有空值导致,对表进行异常值空值的数据过滤、去重处理、关联字段加盐、两表mapsideJoin等操作解决数据倾斜问题
(3) 任务执行很慢:
如果不存在reduce数据量过大的情况,则可能该节点问题,导致任务执行慢,开启mapreduce的推测执行设置,重启一个任务,新的任务短时间完成.
如果大部分的任务执行时间都很长,可能是reduce数量不够,可以设置增加并行度解决。
另外检查sql脚本是否存在可优化的操作:例如大量小文件、只有一个reduce等情况
1、spark内存模型,如何解决OOM问题?如何解决SOF问题?
Spark中的OOM问题不外乎以下三种情况:
map执行中内存溢出
shuffle后内存溢出
driver内存溢出
前两种情况发生在executor中,最后情况发生在driver中。我们针对每种情况具体分析
Driver Heap OOM
原因:2. 从Executor端收集数据回Driver端
解决方法:
2.1. 本身不建议将大的数据从Executor端, collect回来. 建议将Driver端对collect回来的数据所做的操作, 转化成Executor端RDD操作.
2.2. 如若无法避免, 自我评collect需要的内存, 相应增加driver-memory的值
Executor heap OOM
分几种情况:map过程产生大量对象导致内存溢出、数据倾斜导致内存溢出、coalesce调用导致内存溢出、shuffle后内存溢出。
1. map过程产生大量对象导致内存溢出:
这种溢出的原因是在单个map中产生了大量的对象导致的,针对这种问题,在不增加内存的情况下,可以通过减少每个Task的大小,以便达到每个Task即使产生大量的对象Executor的内存也能够装得下。具体做法可以在会产生大量对象的map操作之前调用repartition方法,分区成更小的块传入map。例如:rdd.repartition(10000).map(x=>for(i <- 1 to 10000) yield i.toString)。
面对这种问题注意,不能使用rdd.coalesce方法,这个方法只能减少分区,不能增加分区,不会有shuffle的过程。
2.数据不平衡导致内存溢出:
数据不平衡除了有可能导致内存溢出外,也有可能导致性能的问题,解决方法和上面说的类似,就是调用repartition重新分区
3.coalesce调用导致内存溢出:
例如在coalesce之前有100个文件,这也意味着能够有100个Task,现在调用coalesce(10),最后只产生10个文件,因为coalesce并不是shuffle操作,这意味着coalesce并不是按照我原本想的那样先执行100个Task,再将Task的执行结果合并成10个,而是从头到位只有10个Task在执行,原本100个文件是分开执行的,现在每个Task同时一次读取10个文件,使用的内存是原来的10倍,这导致了OOM。解决这个问题的方法是令程序按照我们想的先执行100个Task再将结果合并成10个文件,这个问题同样可以通过repartition解决,调用repartition(10),因为这就有一个shuffle的过程,shuffle前后是两个Stage,一个100个分区,一个是10个分区,就能按照我们的想法执行。
4.shuffle后内存溢出:
shuffle内存溢出的情况可以说都是shuffle后,单个文件过大导致的。
调整executor中shuffle操作的占比
spark.default.parallelism参数增大并行度
2.SQL很熟练,面试没遇到过不会的.一些业务SQL(留存,在线时长,漏斗,连续登陆天数,共同关注好友等等等)也写的很熟练.
共同好友
select
t1_uid
,t2_uid
,count(t1_tuid) cnt
from
(select
t1.uid t1_uid
,t1.tuid t1_tuid
,t2.uid t2_uid
,t2.tuid t2_tuid
from
(select uid,tuid from weixin_friends) t1
join
(select uid,tuid from weixin_friends) t2
on t1.tuid = t2.tuid and t1.uid < t2.uid
)t
group by
t1_uid
,t2_uid
3.如何保证数据质量,数据一致性?
4.数据指标如何保证一致性?
如何评估数据质量的好坏,业界有不同的标准,我总结了以下六个维度进行评估,包括完整性、规范性、一致性、准确性、唯一性、及时性。
1.数据完整性
完整性指的是数据信息是否存在缺失的状况,数据缺失的情况可能是整个数据记录缺失,也可能是数据中某个字段信息的记录缺失。
2.数据规范性
规范性指的是描述数据遵循预定的语法规则的程度,是否符合其定义,比如数据的类型、格式、取值范围等。
3.数据一致性
一致性是指数据是否遵循了统一的规范,数据集合是否保持了统一的格式。数据质量的一致性主要体现在数据记录的规范和数据是否符合逻辑,一致性并不意味着数值上的绝对相同,而是数据收集、处理的方法和标准的一致。常见的一致性指标有:ID 重合度、属性一致、取值一致、采集方法一致、转化步骤一致。
4.数据准确性
准确性是指数据记录的信息是否存在异常或错误。和一致性不一样,存在准确性问题的数据不仅仅只是规则上的不一致,更为常见的数据准确性错误就如乱码,其次异常的大或者小的数据也是不符合条件的数据。常见的准确性指标有:缺失值占比、错误值占比、异常值占比、抽样偏差、数据噪声。
5.数据唯一性
唯一性指的是数据库的数据不存在重复的情形。比如真实成交 1 万条,但数据表有 3000 条重复了,成了 1.3 万条成交记录,这种数据不符合数据唯一性。
6.数据及时性
及时性是指数据从产生到可以查看的时间间隔,也叫数据的延时时长。比如一份数据是统计离线今日的,结果都是第二天甚至第三天才能统计完,这种数据不符合数据及时性。
5.拉链表了解吗?什么情况用到,怎么实现?
6.对于缓慢变化的数据,在数据仓库中是如何处理的
1.原样保留或者重写,这种方式理论上都是取最新的值作为维度的最终的取值,每个维度保留一条数据。这种处理方式是最简单的,直接将原系统的维度同步过来使用就可以,不用做过多的处理。
2.插人新的维度行,每当维度发生变化的时候,插入新增的一行。采用此种方式,保留历史数据,
维度值变化前的事实和过去的维度值关联,维度值变化后的事实和当前的维度值关联。也就是一个维度会存在多行的数据,按时时间范围将维度与事实表关联。
3.添加维度列,采用这种方式,主要是为了将变化前后记录的事实归为变化前的维度或者归为变化后的维度。也就是将产生变化的维度,可以在汇总的时候按照统一分组处理。
4.历史拉链表,用维度记录的开始时间和结束时间来记录。
mr、spark的shuffle有什么不同
MR数据倾斜怎么处理
1、在map端提前进行conmbiner合并,减少数据传输量
在Mapper加上combiner相当于提前进行reduce,即把一个Mapper中的相同key进行了聚合,减少shuffle过程中传输的数据量,以及Reducer端的计算量。
如果导致数据倾斜的key大量分布在不同的mapper的时候,这种方法就不是很有效了。
2、增加reduce并行度
3、导致数据倾斜的key 大量分布在不同的mapper
局部聚合加全局聚合。
跑spark的过程中当某个节点压力过大,怎么调优
spark shuffle 本地化
为什么要划分stage
因为程序是分布式集群中运行的,一个Stage依赖于另一个Stage的结果,并且执行是有先后顺序的,所以要划分
因为程序是分布式集群中运行的,划分Stage的原因是由于任务类型的不一致:宽依赖和窄依赖。有的任务只依赖于一个父的RDD:一个Stage依赖于另一个Stage的结果,所以可以和父RDD放到同一task中执行,构成一个Stage。但是有的任务(例如reduce,group)等,需要的是全局数据,依赖于多个分区的处理结果,所以只等等待前面的执行,这就有了先后顺序(Stage),所以要划分。
划分出来的stage是放在集群中运行的,其中每个stage有多个task。每个task的逻辑一样,只是对应的分区是不相同。这多个task被分布在不同的机器上并发执行。不同的资源调度框架:Yarn、Mesos、Local等生成的DAG是完全一样,可以跨平台运行保证结果。
每个stage由多个task组成,这些task在任务逻辑上是一致的只是对应不同的分区。Partition的数量和同一任务逻辑的Task的数量是一致的,也就是说一个分区会被对应的stage的一个task处理,由多个Executor争抢。如果计算资源充足,一个Executor执行一个,不足会计算多个task。
spark任务出问题,怎么定位
spark shuffle了解吗,说一下,知道shuffle service吗
spark 的join
MR 过程中有几次排序过程 4
总共可能发⽣4次排序过程:
1.Map阶段
环形缓冲区:当缓冲区的数据达到阈值后,对缓冲区数据进⾏⼀次快速排序,再⼀些到磁盘。排序⼿段:快速排序(会⼿写)
溢写到磁盘中:当数据处理完毕后,所有⽂件进⾏归并排序。排序⼿段:分区归并排序(会⼿写)
2.Reduce阶段
按照指定分区读取到reduce缓冲中(不够则落盘):磁盘上⽂件数据达到⼀定阈值,进⾏⼀次归并排序以⽣成更⼤的⽂件。排序⼿段:归并排序
Reduce task前分组排序:当所有⽂件拷贝完毕后,Reduce Task统⼀对内存和磁盘上所有数据进⾏⼀次归并排序。
hive三级分区怎么解决小文件问题
解决小文件的问题,首选方案就是 “hive合并小文件”。
可以根据如下思路去解决:
方式一:对已有的数据进行定时或实时的小文件合并
方式二:在生成小文件前,进行相关的配置合并来预防
方式三:使用HAR归档文件
3.1 方式一:处理已有的小文件
3.1.1 insert overwrite 。。。。。。。 distribute by 命令
处理已有的小文件可以实时或定时操作,定时操作可在访问低峰期操作,如凌晨2点。
举例:控制dt分区目录下生成100个文件,且文件大小基本一致,那么hsql如下:
insert overwrite table test partition(dt)
select *
from test
distribute by cast(rand()*100 as int);
3.1.2 concatenate 命令
如果是orc格式存储的表,还可以使用如下命令进行小文件的合并:
alter table test [partition(…)] concatenate
3.2 方式二:预防小文件
通过调节hive参数的方式预防,配置与注释如下(在hive-site.xml配置也可以)
3.3 方式三:使用HAR归档文件
运用于每日定时脚本,对于已经产生小文件的hive表可以使用har归档,而且hive提供了原生支持
set hive.archive.enabled= true ;
set hive.archive.har.parentdir.settable= true ;
set har.partfile.size=256000000;
ALTER TABLE ad_dev.wlb_tmp_smallfile_20210118 ARCHIVE PARTITION(pt=‘2022-03-01’);
其他
如何进行etl链路优化
如果链路慢,但是没有sla风险,怎么优化(类似上一道题)
怎么数据链运行慢定位问题,对任务进行优化
外部表数据变动怎么和外部表建立联系
三种方式:
直接load
msck repair
上传数据之后添加分区
算法
二叉树遍历和还原
单词搜索(给一个list的字符串集合,快速判断,前缀树实现),一个字符串的单词搜索,时间复杂度是多少
有一种将字母编码成数字的方式:‘a’->1, ‘b->2’, … , ‘z->26’。 现在给一串数字,返回有多少种可能的译码结果。如输入’12’,输出2.
dfs一顿做,a了八十,然后和面试官说可以dp,dp讲了一下思路,面试官觉得没问题。
- 输入int n, 返回他的二进制有几个1
- 输入int n, 返回二进制[1,n]一共有几个1
算法:判断域名A是不是B的子域
算法题:返回一个用当前数的各位数字组成的比输入数大的最小的数,比如1234返回1243
算法题:小内存,在一亿条URL里面查找出现次数最多的URL
考察点
考察点 1:MapReduce 思想,利用中间文件存储,分而治之。
考察点 2:排序算法
解题思路
100 亿 *64/1024/1024/1024=596G,可考虑分成 1000 个文件处理,每 个文件大约 600M。
1.顺序读取文件,每行按照 hash(url)%1000 的结果将 url 写入到 1000 个文件中,这 个过程是 mapreduce 中的 map。
2.针对每个小文件,使用 hashmap 统计每个 url 出现的次数,并使用堆排序得到访问 次数最高的前 100 个 url。
3.将每个文件排序好的 100 个 url 及对应的 count 输出到 1000 个文件,最后将这个 1000 个文件(此时每个文件只有 100 行 ) 进行合并排序。