美团大数据开发社招 (附答案)

给大家分享一篇美团大数据开发 1 面的面经。

面试时间:90 分钟

面试方向:大数据开发

面试工具:视频面

面试难度 :⭐⭐⭐⭐

关注公众号:3分钟秒懂大数据,回复:史上最全系列,领取全网最全面的大数据知识点、面经总结!

面试环节

1 面试官:先做个自我介绍。

面试官,您好! 我叫 xxx , xxxx 年 x 月毕业于 xxx 学校,xx 学历,目前就职于 xxx 公司 xxx 部门,职位为:大数据开发工程师,主要从事于 Flink 流计算组件、平台的开发工作。

工作以来,我先后参加了 xxx 项目、xxx 项目以及 xxx 项目,积累了丰富的项目经验,同时,这 x 个项目都得到了领导的一致好评。

我对流计算组件有着浓厚的兴趣,工作之余经常钻研技术、例如:Flink 四大基石、Flink 内核应用提交流程、Flink 调度策略等。

入职 x 年,曾荣获优秀员工,以上是我的自我介绍,请面试官提问。

2 面试官: 我这边先问一些你的基础问题,考察一下你的基本功扎实不。

求职者:好的。

分布式理论

1 什么是事务呢?

事务一般指的是逻辑上的一组操作,或者单个逻辑单元执行的一系列操作。这些操作要么执行成功,要么执行失败。

同时事务包含 ACID 四大特性。

1. A(Atomic)原子性:操作要么成功,要么失败。
2. C(Consistency)一致性:指执行之前和执行之后,数据始终处于一致的状态。
3. I(Isolation)隔离性:指并发执行的两个事务之间互不干扰。
4. D(Durability)持久性:指事务提交完成后,此事务对数据的更改操作会被持久化到数据库中,并且不会回滚。

2 分布式事务和事务有啥区别?

分布式事务指将海量数据分散的存储到多台服务器的多台数据库中,同时要具备 ACID 特性。

分布式事务支持 CAP 理论 和 Base 理论

3 CAP 理论可以介绍一下吗?

C(Consistency)一致性:对所有的数据副本在进行增删查操作时,要么全部执行成功,要么全部执行失败。

A(Availability)可用性:指客户端访问数据的时候,能够快速得到响应。所有的请求都会被响应,不会存在响应超时或响应错误情况,如果对不同应用程序设置超时响应时间,一旦超过这个时间,系统将不可用。

P(Partition Tolerance)分区容忍性:一个节点挂掉后,不影响其他节点对外提供服务。

在分布式系统中,不会同时具备 CAP 三个特性,只能具备其中的两个。

4 那 Base 理论呢?

Base 理论是对 CAP 理论中 AP 理论的一个扩展,它通过牺牲强一致性来获得可用性。

Base 理论是 基本可用(Basically Available)、软状态(Soft State)、和最终一致性(Eventually Consistent)的缩写。当系统出现故障时,Base 理论允许部分数据不可用,但是会保证核心功能能用;允许数据在一段时间内不一致,但是经过一段时间,数据最终是一致的。

ok.

5 面试官:在大数据组件中,你们一般用的资源管理框架是哪个?

更多的使用 Yarn 作为资源管理工具,现在一大部分业务也上云了,使用的 K8S。

6 面试官:那你能谈一下 yarn 的基础架构及调度流程吗?

yarn 的基础架构主要包含 3 大组件,分别为 ResourceManager、ApplicationMaster、NodeManager.

其中:

ResourceManager 是一个全局的资源管理器,负责整个系统的资源管理和分配,主要包括两个组件,即调度器(Scheduler)和应用程序管理器(Applications Manager)。

ApplicationMaster:ApplicationMaster 是 Resource Manager 根据 接收用户提交的作业,按照作业的上下文信息等 分配出一个 container 资源,然后 通知 NodeManager 为用户作业创建出一个 ApplicationMaster。

NodeManager:NodeManager 管理 YARN 集群中的每个节点,对节点进行资源监控和健康状态管理。

yarn 的调度流程简单总结如下:

1. 客户端提交应用程序给 ResourceManager
2. ResouceManager 收到请求后,将分配 Container 资源,并通知对应的 NodeManager 启动一个 ApplicationMaster。
3. applicationMaster 来运行和管理 container 里面的任务,其中 container 会通过心跳机制向 applicationMaster 来发送运行信息。
4. 任务完成之后,application 向 ResourceManager 报告,任务完成,container 进行资源释放。

面试官: 好的,你这边主要是面向实时的,那一些离线的工作内容都了解吗?(准备给求职者挖坑呀,面试官这样一问,估计组内是做离线内容的。)

求职者:简单了解些(这时候话别说的太满,简单刚好

7 面试官:Hive 的工作机制了解吗?

Hive 是一个基于 Hadoop 的数据仓库工具,可以将结构化的数据文件映射为一个表。并提供类 SQL 查询功能。

其中 底层计算方式是基于 MapReduce 来做运算,计算后的数据存储到 HDFS 中。

所以 Hive 利用 HDFS 存储数据,利用 MapReduce 查询数据,利用 Mysql 存储元数据。

8 面试官:Hive sql 到 MapReduce 转化的流程清楚吗?

Hive 将 SQL 转化为 MapReduce 任务,整个编译过程分为以下几个阶段:

1\. sql 解析。HIve 通过 Antlr 对 SQL 进行 词法、语法解析,生成抽象语法树 AST Tree。

2\. 语法解析。遍历 AST Tree,抽象出查询的基本组成单元 QueryBlock

3\. 生成逻辑执行计划。遍历 QueryBlock,翻译为执行操作树 OperatorTree

4\. 优化逻辑执行计划。 逻辑层优化器进行 OperatorTree 变换,合并不必要的 ReduceSinkOperator,减少 shuffle 数据量。

5\. 生成物理执行计划。遍历 OperatorTree,翻译为 MapReduce 任务。

6\. 优化物理执行计划。物理层优化器进行 MapReduce 任务的变换,生成最终的执行计划。

9 面试官:Hive shuffle 过程清楚吗?

Shuffle 的正常意思是洗牌或弄乱。

在 MapReduce 框架中,shuffle 是连接 Map 和 Reduce 之间的桥梁,Map的输出到 Reduce 中必须经过 shuffle 这个环节,shuffle 的性能高低直接影响了整个程序的性能和吞吐量。

简单来说:Shuffle 描述着数据从 map task 输出到 reduce task 输入的这段过程。

大部分 map task 与 reduce task 的执行是在不同的节点上。当然很多情况下Reduce 执行时需要跨节点去拉取其它节点上的 map task 结果。

10 面试官:spark 中 RDD 的血缘关系介绍一下?

RDD 的血缘关系描述的是一个 RDD 如何从父 RDD 计算得来的。如果某个 RDD 丢失了,则可以根据血缘关系,从父 RDD 计算得来。

举个例子:如提交了一个任务,这个任务在执行过程中生成了一个完整的 DAG 图。那么这个 DAG 中的一系列处理就被称为一个血缘关系,即 DAG 拓扑排序的结果。

在血缘关系中,下一代的 RDD 依赖于上一代的 RDD。B 依赖于 A,D 依赖于 C,而 E 依赖于 B 和 D 等。

数据倾斜

11 面试官:数据倾斜是什么原因造成的,如何解决?

数据倾斜问题主要指 shuffle 过程中出现的数据倾斜问题,是由于不同
的 key 对应的数据量不同,而导致不同 task 所处理的数据量不同的问题。

如何解决:可以分为以下几点。

1\. 空值引发的数据倾斜问题。当一个表中 null 值非常多,如果这张表进行 join 操作,那必然会有 shuffle 产生,这样所有的 null 值都会被分配到一个 reduce 中,必然产生数据倾斜。

解决办法:

(1)直接不让 null 值参与 join 操作。在写 sql 时,直接将有null 的过滤掉。
(2)或者 给 null 值随机赋值。因为 null 值参与 shuffle 时的 hash 结果是一样的,那么我们可以给 null 值随机赋值,这样它们的 hash 结果就不一样,就会进到不同的 reduce 中。

2\. 不同数据类型引发的数据倾斜

比如当两张表 join 操作时,A 表需要 join 的字段类型为 int 型,B 表需要 join 的字段类型既包含 int ,又包含 string 类型。 当进行 A left join B 时,默认的 hash 操作会按照 int 类型的 id 进行分配。这时 所有的 string 类型会被分配到同一个 id 下。若数据量过大,必会造成数据倾斜问题。

解决办法:

我们 直接把 int 类型都转为 string 就好了,这样 key 字段都为 string,
hash 时就按照 string 类型进行分配。

3\. key 数据分布不均所造成的数据倾斜

解决办法:

1. 单独处理倾斜 key,为大数据量 key 添加随机数前缀,将其分散到多个任务中进行预聚合操作,然后将随机数前缀去掉,再和其他数据进行聚合操作。

4\. 将 sort by 改为 order by

因为 sort by 为全局排序,会导致所有 map 端数据都进入一个 reduce 中,在数据量特别大时会长时间处于计算状态。使用 order by 会启动多个 reduce 进行排序。

5 使用 Mapjoin 避免数据倾斜的手段

允许在 map 阶段进行 join 操作,MapJoin 把小表全部读入内存中,在 map 阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在 map 是进行了 join 操作,省去了 reduce 运行的效率也会高很多。

Flink 组件

12 面试官:问一些 Flink 基础,Flink 提供几种时间语义,并且 watermark 机制介绍一下?

Flink 提供三种时间语义,即事件时间(event time)、摄入时间(ingestion time)和处理时间(processing time)

WaterMark 主要是用来处理数据延迟、数据丢失问题,一般和 window、processingTime 结合使用。

通过对 window 添加 waterMark 来处理迟到的数据。

WaterMark 包含两种 周期水位线标点水位线

13 面试官:定期水位线 和 标点水位线 有什么区别?应用于什么场景?

定期水位线:定期水位线(Periodic Watermark)按照固定时间间隔生成新的水位线,默认 200 ms。

使用场景: 对迟到数据要求不是很严格的场景下使用。

标点水位线(Punctuated Watermark)通过数据流中某些特殊标记事件来触发新水位线的生成。这种方式下窗口的触发与时间无关,而是决定于何时收到标记事件

使用场景: 在实时性要求非常高的场景才会选择 Punctuated 的方式进行 Watermark 的生成。

14 面试官: 标点水位线 怎么触发 waterMark?

标点水位线 需要实现 AssignerWithPunctuatedWatermarks API 接口,然后重写 两个方法:
(1)createTimestampAssigner 主要是从消息中提取事件时间。

(2)createWatermarkGenerator 主要是用于检查事件是否标点事件,当返回值非 null 并且新生成的水位线大于当前水位线,则触发窗口计算。

15 面试官: 你说一下 Flink checkpoint、state 的底层逻辑?

先介绍 checkpoint

首先,checkpoint 叫做检查点,是 Flink 实现容错机制的最核心功能,它能根据配置周期性的基于 Stream 中各个 Operator 的状态来生成
Snapshot 快照,从而将这些状态数据定期持久化存储下来,当 Flink 程序一旦意外崩溃时,重新运行程序时可以有选择地从这些 Snapshot 进行恢复。

Flink 的 checkpoint 机制原理来自“Chandy-Lamport algorithm”算法

再介绍 state

state 一般指一个具体的 Task/Operator 的状态,主要是用来保存中间的 计算结果 或者 缓存数据

state 按照 Flink 管理还是用户管理分为:RowState(原始状态)和 Managedstate(托管状态)
1. RowState 由用户自行管理,只支持 字节 数组,所有状态都要转换为二进制字节数组才可以。
2. ManagedState 由 Flink RunTime 管理,支持多种数据结构,如 Map List 等

State 按照 key 划分,可以分为 KeyedState,OperatorState.

keyedState 只能用在 keyStream 上,并且每一个 key 对应一个 state 对象,keyedState 保存在 StateBackend 中,通过 RuntimeContext 访问,实现 Rich Function 接口,支持多种数据结构,如 ListState、MapState、AggregatingState 等

OperatorState 可以用于所有算子,但整个算子只对应一个 state,实现 CheckpointedFunction 或者 ListCheckpointed 接口,目前只支持 ListState 数据结构。

16 面试官: 状态存储到 HDFS 中,一般会出现什么问题?

首先,状态存储在 HDFS 中,是基于文件型的状态存储方式。当 job 运行时所需的 State 数据会全部保存在 TaskManager 的内存中,执行检查点的时候,会把 State 的快照数据保存到配置的 HDFS 中。

当同一个集群的 Job 到达一定数量后,会对 HDFS 造成非常大的压力。同时读取 HDFS 中的数据会频繁进行 IO 交互,读取速度相对内存来说,慢很多。

17 面试官: 如果 checkpoint 设置 10s 一次,状态存储到 HDFS 中,会出现什么问题?

如果每隔 10s 就进行 checkpoint,假如 checkpoint 时,状态过小,而 HDFS 的块大小是以 128 M 进行划分,往 HDFS 中写状态时,不可能每次都把 128M 写满,所以就会出现大量的小文件。

这样会反过来影响 HDFS 读文件的效率,导致读取速度非常慢,加大 yarn 集群的负担,从而拖垮整个集群的效率。

18 面试官:Flink on k8s 的设计思路能描述一下吗?

目前将组件进行容器化已经成为当前的一个趋势,将 Flink 集群部署到 K8S 上 可以实现资源的合理利用,同时 k8s 是一个开源的容器集群管理系统,可以实现容器集群的 自动化部署、自动扩缩容、维护 等功能。

而 在 K8s 上部署 Flink 集群,主要包含以下几个步骤:

1 启动集群
1. Flink 客户端使用 Kubectl 或者 K8s 的 Dashboard 提交 Flink 集群的资源描述文件,包含 4-5个 yaml 文件。

2. K8s Master 根据这些资源文件将请求分发给 Slave 节点,创建 Flink Master Deployment、TaskManager Deployment、ConfigMap、SVC 四个角色。同时初始化 Dispatcher 和 KubernetesResourceManager。并通过 K8S 服务对外暴露 Flink Master 端口。

3. Client 用户使用 Flink run 命令,通过指定 Flink Master 的地址,将相应任务提交上来,用户的 Jar 和 JobGrapth 会在 Flink Client 生成,通过 SVC 传给 Dispatcher。

4. Dispatcher 收到 JobGraph 后,会为每个作业启动一个 JobMaster,将 JobGraph 交给 JobMaster 进行调度。

5. JobMaster 会向 KubernetesResourceManager 申请资源,请求 Slot。

6. KubernetesResourceManager 从 K8S 集群分配 TaskManager。每个 TaskManager 都是具有唯一标识的 Pod。KubernetesResourceManager 会为 TaskManager 生成一份新的配置文件,里面有 Flink Master 的 service name 作为地址,保障在 Flink Master failover 后,TaskManager 仍然可以重新连接上。

7. K8S 集群分配一个新的 Pod 后,在上面启动 TaskManager。
8. TaskManager 启动后注册到 SlotManager。
9. SlotManager 向 TaskManager 请求 Slot。
10. TaskManager 提供 Slot 给 JobManager,然后任务被分配到 Slot 上运行。

19 面试官: 那 Flink on K8S 通信怎么处理?

Flink on K8S 通信 包含 四种通信方式:

1\. POD 内部通信。直接通过 localhost 相互访问就可以。

2\. 同节点的 POD 之间通信。 通过默认的 docker 网桥互连容器直接通信就可。

3\. 不同节点的 POD 之间通信;通过安装 Flannel 组件,pod 的 ip 分配由 flannel 统一分配,通讯过程也是走 flannel 的网桥。

4\. 外部网络与 POD 之间通信。使用 Service 服务,通过 lable 关联到后端的 Pod 容器。

Service 分配的 ip 叫 cluster ip,这是一个固定的虚拟 ip,这个 ip 只能在 k8s 集群内部使用,如果 service 需要对外提供,只能使用 Nodeport 方式映射到主机上,使用主机的 ip 和端口对外提供服务。(另外还可以使用 LoadBalance 方式,但这种方式是在 gce 这样的云环境里面使用的 )。

OK,接下来问一些项目相关的问题,

20 面试官: xxx 平台架构是什么样的?

平台架构主要分为四层:分别为应用层、xxx 基础层、Flink 计算层、存储调度层。

应用层包含 WebUI、REST 方式,主要是一些操作界面等。

xxx 计算层包含 应用管理、资源管理、元数据、脚本管理等核心模块。

Flink 计算层 调用原生 Flink 组件、使用 yarn、K8S 等进行调度。

存储层:包含 HDFS、Hive、Kafka、Hbase、ES、CK 等。

21 面试官: 你们的 Kafka 的 QPS 是多少?

以一个具体的案例介绍:xxx , 当时 Flink 从 Kafka source 端接入每秒 峰值为 2w 条数据。

算法

22 面试官:翻转二叉树说一下思路:

使用递归遍历二叉树时
(1)我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。
(2)如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。

代码实现:

class TreeNode{
  int val;
  TreeNode left;
  TreeNode right;
  TreeNode(int x) { val = x; }
}

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root == null){
            return null;
        }
        TreeNode left = invertTree(root.left);
        TreeNode right = invertTree(root.right);
        root.left = right;
        root.right = left;
        return root;
    }  
}

23 面试官:买卖股票的最佳时机 II

给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。

在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

解题思路:使用动态规划求解。

class Solution {
    public int maxProfit(int[] prices) {
        int[] dp = new int[2];
        // 0表示持有,1表示卖出
        dp[0] = -prices[0];
        dp[1] = 0;
        for(int i = 1; i <= prices.length; i++){
            // 前一天持有; 既然不限制交易次数,那么再次买股票时,要加上之前的收益
            dp[0] = Math.max(dp[0], dp[1] - prices[i-1]);
            // 前一天卖出; 或当天卖出,当天卖出,得先持有
            dp[1] = Math.max(dp[1], dp[0] + prices[i-1]);
        }
        return dp[1];
    }
}
#美团面试##面经##社招##美团#
全部评论
谢谢楼主分享,太详细了 而且有深度 嘻嘻嘻
1 回复 分享
发布于 2022-02-23 13:31
order by 是全局排序 sort by是局部排序 说反了吧
2 回复 分享
发布于 2023-02-16 14:37 江苏
谢谢楼主分享,太详细了 而且有深度 嘻嘻嘻
1 回复 分享
发布于 2022-02-12 20:08
好强
点赞 回复 分享
发布于 2022-03-14 20:59
感觉你们好厉害啊
点赞 回复 分享
发布于 2022-12-27 17:45 广东
点赞 回复 分享
发布于 2023-02-09 15:53 广东

相关推荐

不愿透露姓名的神秘牛友
11-19 10:58
点赞 评论 收藏
分享
21 233 评论
分享
牛客网
牛客企业服务