58同城大数据开发社招面经(附答案)
今天为大家分享一篇 58 同城大数据开发(流计算方向)社招的面经,附上答案。
面试方式通过项目来引出提问的知识点,主要考察面试人员对项目的理解能力以及背后涉及的原理。
面试时间:50 分钟
面试方向:大数据开发(流计算方向)
面试工具:微信视频面
面试难度 ::star::star::star:
面试环节
1 面试官:请简短的做个自我介绍。
面试官,您好!我叫 xxx , xxxx 年 x 月毕业于 xxx 学校,xx 学历,目前就职于 xxx 公司 xxx 部门,职位为:大数据开发工程师,主要从事于 Flink 流计算组件、平台的开发工作。
工作以来,我先后参加了 xxx 项目、xxx 项目以及 xxx 项目,积累了丰富的项目经验,同时,这 x 个项目都得到了领导的一致好评。
我对流计算组件有着浓厚的兴趣,工作之余经常钻研技术、例如:Flink 四大基石、Flink 内核应用提交流程、Flink 调度策略等。
入职 x 年,曾荣获优秀员工,以上是我的自我介绍,请面试官提问。
2 面试官:你做的这些项目主要是数据开发呢还是平台性质的?
主要面向平台,由于组内是研究 Flink 组件的,基于这个组件设计的平台,供公司多个部门使用。
3 面试官:那你介绍一下这三个项目,哪个是你最拿手的,并解决了哪些问题?
那我重点描述一下第三个项目,该平台对标阿里云的实时计算 Flink 平台。XXX 是一个 一站式、高性能的大数据处理平台,底层基于 Flink 实现,平台提供多种核心功能,支持多种 source、sink 插件,内置统一的元数据管理,支持 一键提交、应用管理、断掉调试、监控告警、Ranger 鉴权等多个核心模块。
我主要负责对该平台的 Flink 版本升级、从原先的 Flink 1.11.0 升级到 1.14.0,同时对平台进行架构重构及代码优化,并参与核心模块 应用管理 、Ranger 鉴权模块的开发工作。
主要解决了多部门提交 Flink 任务需要大量开关配置问题, 版本升级后的 SQL 语法校验、应用提交报错问题,以及 Ranger 鉴权问题。
4 面试官:应用提交都支持哪些方式?
支持 Flink SQL、Jar 包、画布 3 种方式。
5 面试官:使用 Jar 包提交支持哪些模式?
目前支持 Standalone、yarn 、K8s 三种方式,然后 通过 Yarn 提交时 支持 per job 模式,session 模式( 专门少说了一种方式 )
6 面试官:Flink on yarn 在新版本新增了一种模式,你知道吗? (果不其然,发问了)
知道,新增了 flink on yarn application 模式。该模式的最大特点是 原本在客户端需要做的事全部被提交到了 jobManager 中进行,也就是说 main()方法在集群中执行(入口点位于 ApplicationClusterEntryPoint ),客 户端只需要负责发起部署请求即可。
7 面试官:Flink on yarn application 设计的优点在哪?
首先 yarn-per-job 和 yarn-session 模式下,客户端都需要执行以下三步,即:
-
获取作业所需的依赖项;
-
通过执行环境分析并取得逻辑计划,即 StreamGraph→JobGraph;
-
将依赖项和 JobGraph 上传到集群中。
如下图简易版:

只有在这些都完成之后,才会通过 env.execute()方法 触发 Flink 运行时真正地开始执行作业。
如果所有用户都在 同一个客户端
上提交作业,较大的依赖会消耗更多的带宽,而较复杂的作业逻辑翻译成 JobGraph 也需要吃掉更多的 CPU 和内存,客户端的资源反而会成为瓶颈。
Application 模式。将原本需要在客户端做的三件事都被转移到了 JobManager 里,客户端只需要负责发起部署请求。大大减小了 客户端 CPU 和内存的使用资源。简易版原理图如下:

8 面试官:平台进行架构重构及代码优化,这块是如何设计的?
开发初期,使用人过少,且合作部门只有一个,只采用单接口设计、后期多部门合作时,之前设计的架构会导致每个部门都需要单独维护一个版本。
经过问题分析后,对之前的代码进行解构,其核心思想在于独立每个业务场景的 Web 上下文,通过 WebInstall 接口实现,让其他多部门实现其接口。
WebInstaller 里面定义了 3 个方法,分别为 inin(),run(),close().
init()负责初始化工作、如配置文件加载,数据库初始化等。run()负责启动,例如 Metric、Watchdog 等;close()负责 Web 服务关闭,会被作为关闭钩子函数(ShutdownHook)注册起来。
xxx 作为主类,会在运行时根据配置参数反射生成不同的 WebInstaller,从而实现在不同业务场景下运行其对应的 Web 服务,从根本上去掉了大量开关配置。
9 面试官:看你解决了 SQL 校验问题,Flink SQL 提交流程包含哪几步?
Flink sql 在被提交到集群之前都需要先被转换成 Transformations,然后编译成 StreamGraph,通过优化生成 JobGraph.
在被转为 Transformations 时主要涉及两大阶段:
-
SQL 语句到 Operation 的转换,即 Parse 阶段;
-
Operation 到 Transformations 的转换,即 Translate 阶段。
在 Parse 阶段一共包含 parse、validate、rel、convert 四个部分。
在 Translate 阶段 一共包含 translateToRel、optimize、translateToExecNodeGraph 和 translateToPlan 四个阶段。
原理图如下:

10 面试官:在 SQL 校验环节做了哪些操作?
SQL 校验环节主要是对经过 parser 解析出的 AST 进行有效性验证,验证的方面主要包括两方面: 1 表名、字段名、函数名是否正确,如在某个查询的字段在当前SQL位置上是否存在或有歧义 2 特定类型操作自身的合法性.
11 面试官:Ranger 鉴权模块是干什么的?
我们的 xxx 作为一个流计算平台,提供给第三方时,要保证数据的安全性。
所以需要对用户提交的 SQL 基于 ranger 信息进行鉴权,确定其权限。
实现步骤:
鉴权主要有三大模块
1 逻辑计划解析:解析 xxx sql ,拦截执行计划.
2 flink-ranger 插件自研:将 flink sql 库、表、字段等操作信息,转换成 ranger 鉴权所需信息,完成鉴权。
3 ranger 策略同步:将 ranger 配置策略,同步到自研插件中。
具体的实现流程:
鉴权在 xxx 中主要分为 3个步骤:
1 用户在平台上 执行 sql ,通过 flink-planner 模块进行 sql 解析,并执行。
2 拦截 flink 源码中#executeOperation,获取 sql 操作的具体细节。
3 将 sql 按照 DDL\DML\DQL 等方式,分别包装为 ranger 鉴权信息,完成鉴权。
12 面试官:看你介绍时提到平台包含监控告警模块,是通过什么进行监控的,主要监控哪些指标?
通过 Flink Metrics 对指标进行监控。使用 Flink 提供的主动方式 PrometheusPushGatewayReporter 方式 通过 prometheus + pushgateway + grafana 组件搭建 Yarn 提交模式进行可视化监控
主要监控 (JM、TM、Slot、作业、算子)等相关指标。以及集群 CPU、内存、线程、JVM、网络等运行组件的指标。
13 面试官:Flink Metrics 提供了几种监控指标类型?分别是哪些?
Flink Metrics 一共提供了四种监控指标:分别为 Counter、Gauge、Histogram、Meter。

-
Count 计数器统计一个指标的总量
-
Gauge:反映一个指标的瞬时值。比如要看现在 TaskManager 的 JVM heap 内存用了多少,就可以每次实时的暴露一个 Gauge,Gauge 当前的值就是 heap 使用的量。
-
Meter:平均值,用来记录一个指标在某个时间段内的平均值。Flink 中的指标有 Task 算子中的 numRecordsInPerSecond,记录此 Task 或者算子每秒接收的记录数。
-
Histogram:直方图,用于统计一些数据的分布,比如说 Quantile、Mean、StdDev、Max、Min 等,其中最重要一个是统计算子的延迟。此项指标会记录数据处理的延迟信息,对任务监控起到很重要的作用。
14 面试官:我看你简历中写了对 全链路吞吐
、 全链路时延
、 吞吐时延
指标进行监控和调优,全链路时延是怎么计算的?
全链路时延指的是 一条数据
进入 source 算子到 数据预处理算子
直到最后 一个算子
输出结果的 耗时
,即处理一条数据需要多长时间。 包含算子内处理逻辑时间,算子间数据传递时间,缓冲区内等待时间
。
全链路时延要使用 latency Marker 计算。latency Marker 是由 source 算子根据当前本地时间生成的一个 marker ,并不参与各个算子的逻辑计算,仅仅跟着数据往下游算子流动,每到达一个算子则算出当前本地时间戳并与 source 生成的时间戳相减,得到 source 算子到当前算子的耗时,当到达 sink 算子或者说最后一个算子时,算出当前本地时间戳与 source 算子生成的时间戳相减,即得到全链路时延。原理图如下:

15 面试官:全链路时延计算公式怎么计算的?( 重点
)
计算公式:
avg(flink_taskmanager_job_latency_source_id_
operator_id _operator_subtask_index_latency{
source_id="cbc357ccb763df2852fee8c4fc7d55f2",
operator_id="c9c0ca46716e76f6b700eddf4366d243",quantile="0.999"})
16 面试官:怎么实现对吞吐的监控的?比如说怎么知道 source 端的吞吐量?
通过 Flink Metrics 的 Count 计数器,以及 Gauge 可以实现对 source
端吞吐量的监控
17 面试官:我们聊聊 Flink 的一些知识点,说一下 WaterMarker 机制
WaterMark 是用来解决数据延迟、数据乱序等问题。
水印就是一个时间戳(timestamp),Flink 可以给数据流添加水印
-
水印并不会影响原有 Eventtime 事件时间
-
当数据流添加水印后,会按照水印时间来触发窗口计算,也就是说
-
设置水印时间,会比事件时间小几秒钟,表示最大允许数据延迟达到多久
Flink 提供了常规的 定期水位线 以及 定制化的标点水位线 两种生成水位线的方式供用户选择。
(1) 定期水位线:周期性的生成 watermark,系统会周期性的将 watermark 插入到流中。默认周期是 200 毫秒。
(2) 标点水位线:没有时间周期规律,可打断的生成 watermark, 每一次分配 Timestamp 都会调用生成方法。
18 面试官:结合 kafka 说一下,flink 如何实现 exactly once 语义的?
Flink 使用两阶段提交协议 预提交(Pre-commit)阶段和 提交(Commit)阶段 保证端到端严格一次。

(1)预提交阶段
1、当 Checkpoint 启动时,进入预提交阶段,JobManager 向 Source Task 注入检查点分界线(CheckpointBarrier),Source Task 将 CheckpointBarrier 插入数据流,向下游广播开启本次快照,如下图所示:

预处理阶段:Checkpoint 启动
2、Source 端:Flink Data Source 负责保存 KafkaTopic 的 offset 偏移量,当 Checkpoint 成功时 Flink 负责提交这些写入,否则就终止取消掉它们,当 Checkpoint 完成位移保存,它会将 checkpoint barrier(检查点分界线) 传给下一个 Operator,然后每个算子会对当前的状态做个快照,保存到状态后端(State Backend)。
对于 Source 任务而言,就会把当前的 offset 作为状态保存起来。下次从 Checkpoint 恢复时,Source 任务可以重新提交偏移量,从上次保存的位置开始重新消费数据,如下图所示:

预处理阶段:checkpoint barrier 传递 及 offset 保存
3、Sink 端:从 Source 端开始,每个内部的 transformation 任务遇到 checkpoint barrier(检查点分界线)时,都会把状态存到 Checkpoint 里。数据处理完毕到 Sink 端时, Sink 任务首先把数据写入外部 Kafka ,这些数据都属于预提交的事务(还不能被消费),此时的 Pre-commit 预提交阶段下 Data Sink 在保存状态到状态后端的同时还必须预提交它的外部事务,如下图所示:

预处理阶段:预提交到外部系统
(2)提交阶段
4、当所有算子任务的快照完成(所有创建的快照都被视为是 Checkpoint 的一部分),也就是这次的 Checkpoint 完成时, JobManager 会向所有任务发通知 ,确认这次 Checkpoint 完成,此时 Pre-commit 预提交阶段才算完成。才正式到两阶段提交协议的第二个阶段:commit 阶段。该阶段中 JobManager 会为应用中每个 Operator 发起 Checkpoint 已完成的回调逻辑。
所有算子 收到确认通知,就会正式提交之前的事务,Kafka 中未确认的数据就改为“已确认”,数据就真正可以被消费了。如下图所示:

提交阶段:数据精准被消费
19 面试官:Flink HBase 支持 Exactly once 语义吗?
使用 hbase 的幂等性结合 at least Once(flink 中 state 能恢复,在两次 checkpoint 间可能会有重复读取数据的情况)实现精确一次性语义。
20 面试官:Flink HDFS 支持 Exactly once 语义吗?
支持,Flink 中 sink 数据到 HDFS 可以通过 BucketingSink 来完成。
21 面试官:好,我们问一些 kafka 方面的问题,先简单介绍一下 kafka的架构
Kafak 总体架构图中包含多个概念:如下图所示:

(1)ZooKeeper: Zookeeper
负责保存 broker
集群元数据,并对控制器进行选举等操作。
(2)Producer:生产者负责创建消息,将消息发送到 Broker。
(3)Broker: 一个独立的 Kafka
服务器被称作 broker
,broker 负责接收来自生产者的消息, 为消息设置偏移量
,并将消息存储在磁盘。broker 为消费者提供服务,对读取分区的请求作出响应,返回已经提交到磁盘上的消息。
(4)Consumer:消费者负责从 Broker
订阅并消费消息。
(5)Consumer Group: Consumer Group
为消费者组,一个消费者组可以包含一个或多个 Consumer
。
使用 多分区 + 多消费者
方式可以极大 提高数据下游的处理速度
, 同一消费者组中的消费者不会重复消费消息
,同样的,不同消费组中的消费者消费消息时互不影响。Kafka 就是通过消费者组的方式来实现消息 P2P 模式和广播模式。
(6)Topic:Kafka 中的消息 以 Topic 为单位进行划分 ,生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费。
(7)Partition:一个 Topic 可以细分为多个分区, 每个分区只属于单个主题 。同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的 日志(Log)文件 ,消息在被追加到分区日志文件的时候都会分配一个特定的 偏移量(offset) 。
(8)Offset:offset 是消息在分区中的唯一标识, Kafka 通过它来保证消息在分区内的顺序性 ,不过 offset 并不跨越分区,也就是说, Kafka保证的是分区有序性而不是主题有序性 。
(9)Replication: 副本 ,是 Kafka 保证数据高可用的方式,Kafka 同一 Partition 的数据可以在多 Broker 上存在多个副本 ,通常只有 主副本对外提供读写服务 ,当主副本所在 broker 崩溃或发生网络异常,Kafka 会在 Controller 的管理下会重新选择新的 Leader 副本对外提供读写服务。
(10)Record:实际写入 Kafka 中并可以被读取的消息记录。每个 record 包含了 key
、 value
和 timestamp
。
(11)Leader: 每个分区多个副本的 "主" leader,生产者发送数据的对象,以及消费者消费数据的对象都是 leader。
(12)follower: 每个分区多个副本中的"从" follower,实时从 Leader 中同步数据,保持和 leader 数据的同步。Leader 发生故障时,某个 follow 会成为新的 leader。
22 面试官:kafka 如何做到高吞吐量和性能的?
kafka 在写方面通过页缓存技术、磁盘顺序写 实现写数据的超高性能,在读方面通过 零拷贝实现高吞吐和高性能的。
1、页缓存技术
Kafka
是基于 操作系统
的 页缓存
来实现文件写入的。
操作系统本身有一层缓存,叫做 page cache ,是在 内存里的缓存 ,我们也可以称之为 os cache ,意思就是操作系统自己管理的缓存。
Kafka 在写入磁盘文件的时候,可以直接写入这个 os cache 里,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把 os cache 里的数据真的刷入磁盘文件中。通过这一个步骤,就可以将磁盘文件 写性能 提升很多了,因为其实这里相当于是在写内存,不是在写磁盘,原理图如下:

2、磁盘顺序写
另一个主要功能是 kafka 写数据的时候,是以磁盘顺序写的方式来写的。也就是说, 仅仅将数据追加到文件的末尾
, 不是在文件的随机位置来修改数据
。
普通的机械磁盘如果你要是随机写的话,确实性能极差,也就是随便找到文件的某个位置来写数据。
但是如果你是 追加文件末尾 按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能相差无几。
基于上面两点,kafka 就实现了写入数据的超高性能。
3、零拷贝
从 Kafka 里消费数据的时候实际上就是要从 kafka 的 磁盘文件 里 读取某条数据 然后发送给下游的消费者,如下图所示。

那么这里如果频繁的从磁盘读数据然后发给消费者,会增加两次没必要的拷贝,如下图:

一次是从操作系统的 cache 里拷贝到应用进程的缓存里,接着又从应用程序缓存里拷贝回操作系统的 Socket 缓存里。
而且为了进行这两次拷贝,中间还发生了好几次上下文切换,一会儿是应用程序在执行,一会儿上下文切换到操作系统来执行。所以这种方式来读取数据是比较消耗性能的。
Kafka 为了解决这个问题,在读数据的时候是引入零拷贝技术。
也就是说,直接让操作系统的 cache 中的数据发送到 网卡 后传输给下游的消费者, 中间跳过了两次拷贝数据的步骤 ,Socket 缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到 Socket 缓存,如下图所示:

通过 零拷贝技术 ,就不需要把 os cache 里的数据拷贝到应用缓存,再从应用缓存拷贝到 Socket 缓存了,两次拷贝都省略了,所以叫做零拷贝。
对 Socket 缓存仅仅就是拷贝数据的描述符过去,然后数据就直接从 os cache 中发送到网卡上去了, 这个过程大大的提升了数据消费时读取文件数据的性能 。
Kafka 从磁盘读数据的时候,会先看看 os cache 内存中是否有,如果有的话,其实读数据都是直接读内存的。
kafka 集群经过良好的调优,数据直接写入 os cache 中,然后读数据的时候也是从 os cache 中读。相当于 Kafka 完全基于内存提供数据的写和读了,所以这个整体性能会极其的高。
23 面试官:说一下 kafka 的 ISR 机制?
在分区中,所有副本统称为 AR ,Leader 维护了一个动态的 in-sync replica(ISR), ISR 是指与 leader 副本保持同步状态的副本集合
。当然 leader 副本本身也是这个集合中的一员
。
当 ISR 中的 follower 完成数据同步之后, leader
就会给 follower 发送 ack
,如果其中一个 follower 长时间未向 leader 同步数据,该 follower 将会被踢出 ISR 集合,该时间阈值由 replica.log.time.max.ms
参数设定。当 leader 发生故障后,就会从 ISR 集合中重新选举出新的 leader。
24 面试官:如果数据量过大,kafka 会怎么处理?
首先,数据量过大,会造成 1 broker 压力大,2 磁盘压力大,3 消费者压力大,4 log 变大.
这时候需要做的就是,1.扩充 broker,2.挂载多个磁盘,3. 增加消费者,增大消费能力,4 扩分区提升并行能力,5 增大消息批次大小,减少网络请求压力
25 面试官:问一些 java 方面的知识点吧,JVM 内存划分了解吗?
Java 虚拟机在执行 Java 程序的过程中会把它在主存中管理的内存部分划分成5个区域:
1.程序计数器,2.Java 虚拟机栈,3.本地方法栈、4.方法区、5.Java 堆。
其中 程序计数器,Java 虚拟机栈,本地方法栈线程私有,方法区、Java 堆线程共享。对象一般在堆中生成,垃圾回收也在这里发生。
26 说一个算法的实现思路吧。快速排序的实现思路可以简单说一下吗?
快速排序的基本思想: 挖坑填数+分治法 。
它的基本思想是:通过一趟 排序将要排序的数据分割成独立的两部分 ,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快速排序使用分治策略来把一个序列(list)分为两个子序列(sub-lists)。步骤为:
-
从数列中挑出一个元素,称为”基准”(pivot)。
-
重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
-
递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
时间复杂度:O(nlog2n)
27 面试官:好的,我这边暂时就这么多问题啦,你有什么想问的吗?
1 部门主要工作,2 近 1-2 年的规划,3 多久会有下一面通知。
欢迎添加我的微信:拉你进大数据招聘求职群
- 去字节了 ...
- 58同城大数据开发社招面经(附答案)
- 2022年首发|大数据专家级技能模型与学习指南
- Apache Spark源码解析之Maven构建
- Redis 原理 知识点总结 面试必备
- 一文带你掌握 ElasticSearch 原理和技术
- JDK ThreadPoolExecutor核心原理与实践
- Hive 核心知识点灵魂 16 问
- 万字长文带你入门 Hadoop
- kafka用了两年,踩了好多坑,总结一下
- 阿里开源的11个神级项目
- Flink面试干货总结(源码)
- 深入理解Flink Kafka source
- HBase 性能调优指南
- Spark面试八股文(上万字面试必备宝典)
- Spark面试干货总结
- 大数据必须要学会的资源调度平台:YARN!
- 3天,我把 Flink 集群启动、抽象提交源码撸干净了!
- Flink 1.14.0 全新的 Kafka Connector
- 一文了解 Data Lakehouse 的演变