RDD Programming
RDD 核心架构与特性
-
分区(Partitions):数据被切分为多个分区;每个分区在集群节点上独立处理;分区是并行计算的基本单位。
-
计算函数(Compute Function):每个分区应用相同的转换函数;惰性执行机制。
-
依赖关系(Dependencies)
-
窄依赖:1个父分区 → 1个子分区(map、filter)。
-
宽依赖:1个父分区 → 多个子分区(groupByKey、join)。
-
-
分区器(Partitioner):仅存在于键值对RDD;决定数据如何分区,HashPartitioner(默认)、RangePartitioner(有序数据)
-
优先位置(Preferred Locations):数据本地性优化;"移动计算而非数据"原则。
graph LR
A[分区] --> B[计算函数]
B --> C[依赖关系]
C --> D[分区器]
D --> E[优先位置]
RDD 操作类型
-
转换操作(Transformations)
- 单RDD :
map()
,filter()
,distinct()
,无shuffle。 - 双RDD :
union()
,intersection()
,可能触发Shuffle。 - 键值对 :
reduceByKey()
,join()
,通常有Shuffle。
- 单RDD :
-
行动操作(Actions)
- collect:全量数据返回到Driver
- take:取前n条数据。
- count:元素总数。
- reduce:聚合操作。
- foreach:分布式遍历。
-
聚合操作(Aggregate)
- groupByKey:全量数据移动,效率较差。
- reduceByKey:先局部聚合,性能高效。
- aggregateByKey:自定义聚合,较为灵活。
- combineByKey:最底层的API,高度定制化。
RDD 持久化策略
-
存储级别矩阵
级别 内存 磁盘 序列化 副本 适用场景 MEMORY_ONLY
✓ ✗ ✗ 1 默认策略 MEMORY_ONLY_SER
✓ ✗ ✓ 1 减少内存占用 MEMORY_AND_DISK
✓ ✓ ✗ 1 内存不足时 DISK_ONLY
✗ ✓ ✗ 1 超大数据集 OFF_HEAP
- - ✓ 1 避免GC影响
Spark 执行模型
执行流程分层架构
- 用户代码层:开发者编写的 Spark 应用(Transformations/Actions)。
- 逻辑计划层:未优化的计算逻辑表示。
- 物理计划层:优化后的可执行计划。
- 分布式执行层:集群上的任务调度与执行。
核心执行阶段
-
逻辑计划生成:解析操作依赖关系;构建抽象语法树(AST);生成未优化的逻辑计划。
-
物理计划优化(Catalyst引擎)
- 优化流程:解析列/表元数据、(逻辑优化)应用启发式规则、(物理规划)生成可执行计划、(代码生成)编译为字节码。
- 核心优化规则:谓词下推、常量折叠、列裁剪、连接重排序。
-
DAG调度与Stage划分:遇到宽依赖(Shuffle)时划分Stage边界;窄依赖操作合并到同一Stage;形成有向无环图(DAG)。
-
任务调度与执行
-
任务层级结构:
Job:由Action触发的完整计算。
Stage:由无Shuffle依赖的任务组成。
TaskSet:相同Stage的任务集合。
Task:最小执行单元(处理单个分区)。
-
任务调度流程:
DAGScheduler 提交TaskSet ➡️ TaskScheduler 分配资源 ➡️ Executor 启动Task线程 ➡️ Task读取数据并计算➡️ 结果返回
graph LR Driver[Driver程序] -->|创建逻辑计划| DAG[DAGScheduler] DAG -->|划分Stage| TaskScheduler[TaskScheduler] TaskScheduler -->|分发任务| Executor[Executor] Executor -->|执行Task| Worker[Worker节点] Worker -->|返回结果| Driver
-
内存管理机制
- 执行内存:Shuffle/Join/Sort等操作。
- 存储内存:缓存数据和广播变量。
- 动态调整:执行和存储内存可相互借用。
Spark性能调优
资源层优化
- Executor配置公式
- 实例数 = (集群总核数 - 预留核数) / 单Executor核数。
- 内存 = (容器内存 - 1GB) × 0.9(预留10%系统内存)。
- 核数 = 4-5(避免超额订阅)。
- Driver配置策略
- 常规作业:4核8GB。
- 大作业:8核16GB。
- 需collect数据:内存 ≥ 数据集大小 × 1.5。
- 统一内存模型
- 执行内存(60%):Shuffle/Join/Sort操作。
- 存储内存(20%):缓存数据和广播变量。
- 用户内存(20%):UDF等用户数据结构。
- 堆外内存优化:直接操作二进制数据,绕过JVM限制。
执行引擎调优
-
Catalyst优化器
- 核心优化规则:谓词下推提前过滤数据、列裁剪减少处理字段、常量折叠,预先计算常量表达式、优化Join顺序。
- 高级特性:动态分区裁剪,运行时过滤分区;嵌套字段裁剪,处理复杂结构
-
Tungsten引擎
- 堆外内存管理:绕过JVM堆内存限制;减少GC暂停时间;直接操作二进制数据。
- 缓存感知计算:优化数据布局(列式存储);提高CPU缓存命中率;向量化处理指令。
- 全阶段代码生成:将查询编译为单个函数;消除虚拟函数调用;生成JVM字节码或本地代码。
-
Shuffle机制演进
- Hash Shuffle(弃用):每个Mapper为每个Reducer创建文件;产生O(M*R)个文件(M=Mapper, R=Reducer)
- Sort Shuffle(默认):Mapper端排序和合并;每个Mapper输出单个索引文件+数据文件;显著减少小文件数量。
数据处理优化
-
分区策略
场景 适用策略 优势 均匀数值数据 Range分区 有序数据高效处理 键值分布不均 自定义分区 解决数据倾斜 高频Join操作 协同分区 避免Shuffle 时间序列 时间分区 加速时间范围查询 -
数据倾斜
- 检测 :识别热点Key(
groupBy().count()
)。 - 隔离:分离倾斜Key与非倾斜Key。
- 分治:倾斜Key添加随机后缀处理。
- 合并:聚合分治结果。
- 检测 :识别热点Key(