首页 > 大数据开发字节实习一面问题复盘
头像
给xk一个offer吧
发布于 昨天 13:48 江西
+ 关注

大数据开发字节实习一面问题复盘

快手的一面已经寄了,搞不懂为什么。昨天接到了字节实习的面试,还是数据开发岗,问的数据方面的知识和快手比较相似,但字节更注重思维的发散,面试官会多次问有没有新的方法去解决同一个问题。

1.数据仓库的模型有哪些?分别的应用场景是什么?

我实际应用过的数仓模型有 Kimball(维度建模),它是自下而上地来构建数据仓库:先为具体的业务主题(如Home Depot公司的销售情况、订单记录、库存记录)构建面向主题的数据集市,用维度建模的方式对数据进行组织,一般我们采用星型模式,随着时间把多个数据集市通过共享的维度进一步整合成数据仓库。维度建模的方式对用户查询数据非常友好,响应速度很快,因此适用于需要快速处理数据的业务,常用来做报表和数据分析。

现在较为流行的是Data Lake(数据湖架构),把原始大数据存放在湖中,结合仓库层提供结构化分析。

2.具体讲一讲星型模式

星型模式是维度建模中最直观的一种模式,中心是一个或多个事实表,周围放着很多去规范化的维度表,看起来就像一颗星星一样。使用星型模式对数据进行建模的时候,要事先确定好事务的粒度,也就是事实表每一行代表的最小业务含义,比如“供应商填的一笔供货订单”,“Home Depot公司采购部门订的一笔采购订单明细”。利用星型模式建好模之后,我们可以直接使用维度表关联事实表得到我们想要的分析数据。

3.详细讲一讲数仓存储数据时遇到的“慢变维问题”

慢变维是处理数据仓库维度表中维度信息随时间缓慢变化的问题的处理策略,维度表记录了事实表的一些维度信息(工厂名称,工厂地址等),这些描述字段发送变化时,怎样在仓库里保留或者覆盖历史。

常用的“慢变维”策略有三种,

第一种Type 0(保持原值,不允许改变),在维度信息首次加载之后就不允许更新,仓库中永远保留原始的值。这种策略很简单,也很稳定,无法反映维度信息的合法变更,使用场景还是非常少的。

第二种 Type1 (覆盖),如果维度信息发送了改变,就用新的信息直接覆盖掉旧的信息,不保留历史。Type 1策略由于覆盖了之前的旧信息,所以我们无法追溯历史,基于历史事实的一些数据分析就做不了了。

第三种 Type2 新增行/版本化,当维度信息发生了变化,我们保留原行中的旧信息,插入一条新行保存新信息,并用一个字段来记录哪条维度信息是最新的(一般是effective_date/end_date/is_current/version等字段来标识有效区间)。新增行策略可以保留完整的历史数据,可以做一些历史数据的分析,但是维度表随着信息累积会变得非常大,浪费存储空间。

4.Spark和MapReduce的优缺点分别有哪些?

Spark是基于RDD()的内存弹性分布式计算框架,它是利用DAG对计算任务进行调度的,MapReduce是基于标准的Map -> Shuffle -> Reduce流程的计算框架,只能使用磁盘来存储中间数据。

由于Spark可以通过内存来存储中间数据,所以Spark的计算速度是很快的,更适合低延迟的场景,比如交互式查询、流失处理。MapReduce由于频繁使用磁盘存储数据,所以计算速度很慢,只能适用于离线计算。

但是内存的容量毕竟还是有限的,所以如果需要计算的数据过大的话,Spark中内存中存储的数据就会溢写到磁盘,导致性能降低。并且如果计算失误的化,spark由于没有在磁盘中保存中间结果,所以Spark需要从头开始算,这会浪费计算资源。即使Spark设置了RDD lineage来实现容错,但是大量的RDD依赖和长lineage下,重算成本也是比较高的。

5.Spark底层是基于MapReduce开发的,那Spark也会启动Mapper任务对数据做切分吗?

虽然Spark底层是基于MapReduce开发的,但是它的计算流程其实跟MapReduce还是有很大区别。Spark是根据算子来对数据进行操作的,当执行行动算子时,会触发一个Job,spark会把这个Job的计算流程图按“是否需要shuffle”切分成若干个stage,每个stage按分区数拆成多个并行的Task,这些Task分布在多个Executor上执行。总结了来说,Spark会把计算任务细化到一个个Task进行执行,不会走Map Reduce的计算流程。

6.Spark什么时候会用到Shuffle,Shuffle操作是在何处执行的?

只要需要把数据从一个partition重新分布到另一个partition中(跨分区数据重分配)就会触发Shuffle,比如Spark中常用的groupByKey, sortByKey, join, repartiiton(n)等算子。Shuffle是分两个stage在阶段上完成的,第一个是map-side用来读触发Shuffle的上游Stage中的数据,并将处理之后的属于保存到本地shuffle文件中, 第二个是reduce-side读数据,从执行map-side的executor中抓取对应的数据,做最终的合并或者排序处理。最后将处理之后的结果返回给Driver。

关于Spark的详细执行流程和原理我是面试之后复盘了一下再给出答案的,大家可以参考一下尚硅谷老师给出的这张流程图,这张图将job划分成stage,stage拆分成task的流程省略了,这两个操作都是在Driver中完成的。

全部评论

(2) 回帖
加载中...
话题 回帖