spark 面试题

spark 面试题

1、spark 任务如何解决第三方依赖

比如机器学习的包,需要在本地安装?--py-files 添加 py、zip、egg 文件不需要在各个节点安装

2、spark 数据倾斜怎么解决

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

例如,reduce点一共要处理100万条数据,第一个和第二个task分别被分配到了1万条数据,计算5分钟内完成,第三个task分配到了98万数据,此时第三个task可能需要10个小时完成,这使得整个Spark作业需要10个小时才能运行完成,这就是数据倾斜所带来的后果。

数据倾斜的表现

  • Spark 作业的大部分 task 都执行迅速,只有有限的几个task执行的非常慢,此时可能出现了数据倾斜,作业可以运行,但是运行得非常慢

  • Spark 作业的大部分task都执行迅速,但是有的task在运行过程中会突然报出OOM,反复执行几次都在某一个task报出OOM错误,此时可能出现了数据倾斜,作业无法正常运行

定位数据倾斜问题

  • 查阅代码中的shuffle算子,例如reduceByKey、countByKey、groupByKey、join等算子,根据代码逻辑判断此处是否会出现数据倾斜

  • 查看 Spark 作业的 log 文件,log 文件对于错误的记录会精确到代码的某一行,可以根据异常定位到的代码位置来明确错误发生在第几个stage,对应的 shuffle 算子是哪一个

3、spark Driver和Executor

在执行 Spark 的应用程序时,Spark集群会启动DriverExecutor两种JVM进程,

  • Driver:负责创建 spark 上下文,提交 spark 作业 job,并将作业转换为计算任务 task,在各个 Executor 进程间协调任务的调度

  • Excutor:负责在工作节点执行具体的计算任务,并将结果返回给 Driver,同时为需要持久化的 RDD 提供存储功能

4、spark 堆内和堆外内存

spark 内存管理中,涉及到的堆内内存(On-heap Memory)和堆外内存(Off-heap Memory) 两种,因为 Driver 的内存管理相对简单,因此下面说的内存特指的 Excutor 端的内存

Excutor 作为一个 JVM 进程,其内存管理建立在 JVM 内存管理之上,SparkJVM 的堆内空间进行更为详细的分配,以便充分利用内存。同时也引入了堆外内存,使之可以直接在工作节点的系统内存中开辟空间,进一步优化了内存的使用。

堆内内存的大小,由Spark应用程序启动时的–executor-memoryspark.executor.memory参数配置

堆内内存分区

Excutor 堆内内存主要可分为四大块:

  • Excutor 内存:主要用于 shuffle、join、sort、aggregation 等计算过程中的临时数据

  • Storage 内存:主要用于存储 cache 数据,如:rdd 的缓存、unroll 数据

  • 用户内存 User Memory:主要用于存储 rdd 转换操作需要的数据,如:rdd 依赖等信息

  • 预留内存 Reserved Memory:系统预留内存,用于存储 spark 内部对象,防止 OOM,因为 spark 堆内内存大小记录是不准确的,需要留出保险区域(在 Spark 2.2.1 中是写死的,其值等于 300MB,这个值是不能修改的)

# systemMaxMemory 取决于当前 JVM 堆内内存大小,其实就是通过 spark.executor.memory 或 --executor-memory 配置的
可用的存储内存 = systemMaxMemory * spark.storage.memoryFraction * spark.storage.safety Fraction
可用的执行内存 = systemMaxMemory * spark.shuffle.memoryFraction * spark.shuffle.safety Fraction
usableMemory = systemMemory - reservedMemory,这个就是 Spark 可用内存

堆外内存

堆外的空间分配较为简单,只有存储内存和执行内存。

可用的执行内存和存储内存占用的空间大小直接由参数 spark.memory.storageFraction 决定,由于堆外内存占用的空间可以被精确计算,所以无需再设定保险区域

spark.memory.offHeap.enabled true
spark.memory.offHeap.size   10737418240 

两者区别

内存类别区域划分管理方式优缺点
on-heapExecution Memory、Storage Memory、User Memory、Reserved Memory使用 JVM 管理
off-heapExecution Memory、Storage Memory手动管理,不经过JVM可以避免频繁的 GC 但是必须自己编写内存申请和释放的逻辑

参考: Spark内存管理之堆内/堆外内存原理详解

5、spark 血缘关系

父子 rdd 的构建存在依赖关系,通过这种依赖关系可以实现 rdd 的容错,多个连续 rdd 的依赖关系成为血缘关系

每个 rdd 不会保存数据,但会保存血缘关系,若当前 rdd 在计算过程中出现错误,可以根据其保存的血缘关系将数据源重新读取进行计算

参考:Spark 之RDD血缘关系 

6、spark 宽窄依赖

窄依赖

若依赖关系在设计时即可确定,不需要考虑父 rdd 分区中的记录,且父 rdd 中的每个分区最多只有一个子分区

  • rdd 的每个分区最多被一个子 rdd 的分区使用

  • rdd 中的分区要么只依赖一个父 rdd 中的一个分区(如:map、filter 操作)

  • 要么就是在设计时就能确定子 rdd 是 父 rdd 的一个子集(如:coalesce

  • 窄依赖的转换可以在任何的的一个分区上单独执行, 而不需要其他分区的任何信息

宽依赖

  • rdd 的分区被多个子 rdd 的分区依赖即为宽依赖

  • 宽依赖计算时不能随意在某些记录一运行,而是需要使用特殊的方式(如:按照 key 来获取分区中的所以数据)

  • 如:在排序 sort 时,数据必须被分区,同样范围的 key 必须在同一分区

  • 具有宽依赖的 transform 操作包括:sort、reduceByKey、groupByKey、join 和调用 reParation 函数的任何操作

7、常见的 transform和action 操作

  • transform

    • map(func): 返回一个新的 rdd,其结果由每一个输入元素经过 func 函数处理后组成

    • mapPartition(func):类似于 map,但独立地在 rdd 每个分片一运行。假设有 n 个元素,m 个分区,map 的函数将被调用 n 次,而 mapPartition 被调用 m 次,一次处理所有分区

    • flatMap(func):对集合中每个元素进行操作然后再扁平化

    • filter(func):返回一个新的 rddrdd 中每个元素会经过 func 函数的逻辑进行过滤

    • reduceByKey(func, [numTask]):在一个(K,V)RDD上调用,返回一个(K,V)RDD,使用 reduce 函数将相同 key 的值聚合在一起,reduce 任务的个数可以通过第二个参数设置

  • actionfirst、count、collect、saveAsTextFile、take、foraech、countByKey

8、spark 有几种部署方式

  • Local:运行在一台机器上,通常用来练手或者测试

  • Standalone:基于 Master + Slaves 的资源调度集群,spark 任务提交给 Master 运行,是 spark 自身的一个调度系统

  • Yarn:有 yarn-client、yarn-cluster 两种模式,主要区别在于 Driver 程序的运行节点,Spark 客户端直接连接 Yarn,不需要额外构建 Spark 集群

  • Mesos:国内大环境比较少用

### 关于 Spark 的面试问题及答案 #### 什么是 Apache Spark? Apache Spark 是一种快速通用的大规模数据处理引擎,支持内存计算,这使得它比传统的 MapReduce 更加高效。Spark 支持多种编程语言,包括 Scala、Java、Python 和 R,并提供了丰富的 API 来简化数据分析任务[^1]。 #### Spark 中的主要组件有哪些? Spark 主要由以下几个核心组件构成: - **Spark Core**:提供基本的功能,如任务调度、内存管理以及错误恢复。 - **Spark SQL**:用于结构化数据处理,允许用户通过 SQL 查询来操作 DataFrame 或 Dataset。 - **MLlib (Machine Learning Library)**:集成了一系列机器学习算法和实用程序函数。 - **GraphX**:针对图结构的数据集进行了优化的操作。 - **Structured Streaming**:实现了流式数据处理的应用框架。 #### 解释一下 RDD、DataFrame 和 DataSet 的区别是什么? - **RDD (Resilient Distributed Datasets)**:弹性分布式数据集,是最基础的数据抽象形式,适合低级别的API开发。 - **DataFrame**:类似于传统数据中的表格概念,具有模式信息(即列名及其类型),并基于 Catalyst Optimizer 实现自动优化。 - **Dataset**:结合了 RDD 的强类型安全性和 DataFrame 的便捷性,在编译期就能捕获更多错误的同时保持较高的运行效率。 #### 如何利用 Spark UI 进行性能调优? Spark UI 提供了一个直观的 Web 界面让用户可以实时跟踪应用程序的状态,包括但不限于阶段划分、任务进度、输入/输出统计等重要细节。此外,`EXPLAIN` 命令可以帮助理解查询的实际执行路径,而日志文件则记录着更为详尽的过程描述,这些都为发现潜在的问题提供了依据。配合第三方平台比如 Grafana 加上 Prometheus 可以进一步增强集群层面的整体可见度[^2]。 ```sql -- 使用 EXPLAIN 查看查询计划 EXPLAIN SELECT * FROM table_name WHERE condition; ``` #### 动态资源分配如何提升 Spark SQL 表现? 启用动态资源分配可以让 Spark 应用根据实际负载灵活调整使用的 Executor 数量,从而避免因过度预估所需资源而导致的成本浪费或者由于低估造成的工作延迟。合理设置最小最大边界参数有助于找到最佳平衡点,确保既不会因为频繁申释放带来额外开销也不会错过任何可能存在的加速空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值