Spark Core 源码关键环节的深度解析
以下是对 Spark Core 源码关键环节的深度解析,包括核心组件启动与调度机制、Shuffle与调度系统、RDD高级机制。每个环节都细化到具体方法、逻辑、源码片段,附有流程图思路与速记口诀,便于记忆和理解。
一、核心组件启动与调度机制
1. RpcEnv 原理
作用:Spark 分布式组件间消息通信的基础抽象。
实现:支持 Akka(老版)、Netty(主流)。
关键类/方法:
RpcEnv
:抽象通信环境。NettyRpcEnv
:主流实现。RpcEndpoint
:消息接收者。RpcEndpointRef
:消息发送者引用。
源码片段(NettyRpcEnv 初始化):
// 创建 RpcEnv
val rpcEnv = new NettyRpcEnv(conf, name, bindAddress, advertiseAddress, port, securityManager, clientMode)
流程图思路:
- 创建 RpcEnv
- 注册 RpcEndpoint
- EndpointRef 发送消息
- 消息被分发到 Endpoint
口诀:
「Env搭桥,Endpoint通信,Ref发消息,Netty收听」
2. Standalone Master 启动流程
主类:Master
入口:Master.main(args)
→ Master.startRpcEnvAndEndpoint
关键步骤:
- 创建 SparkConf
- 创建 RpcEnv(NettyRpcEnv)
- 启动 MasterEndpoint(负责调度和资源管理)
- 监听端口,等待 Worker/Driver 注册
源码片段:
val (rpcEnv, _, _) = Master.startRpcEnvAndEndpoint(args, conf)
流程图思路:
- main → SparkConf → NettyRpcEnv → MasterEndpoint → 等待注册
口诀:
「Master起飞,Env先备,Endpoint就位,注册才对」
3. Worker 启动
主类:Worker
入口:Worker.main(args)
→ Worker.startRpcEnvAndEndpoint
关键步骤:
- 创建 SparkConf
- 创建 RpcEnv
- 启动 WorkerEndpoint,连接 Master 进行注册
- 资源上报,等待任务分配
源码片段:
val (rpcEnv, _, _) = Worker.startRpcEnvAndEndpoint(args, conf)
流程图思路:
- main → SparkConf → NettyRpcEnv → WorkerEndpoint → 注册到 Master
口诀:
「Worker启动,Env先行,Endpoint注册,资源上供」
4. SparkSubmit 提交流程
主类:SparkSubmit
入口:SparkSubmit.main(args)
关键步骤:
- 解析参数,封装为
SparkSubmitArguments
- 选择对应部署模式(Standalone/Yarn/Mesos)
- 构造并启动 Driver(本地或集群)
源码片段:
val appArgs = new SparkSubmitArguments(args)
appArgs.action match {case SparkSubmitAction.SUBMIT => submit(appArgs)...
}
流程图思路:
- main → 解析参数 → 选择模式 → 启动 Driver
口诀:
「Submit解析,模式选定,Driver启动,任务约定」
5. Driver 启动机制
主类:Driver
(实际就是用户程序)
关键步骤:
- 初始化 SparkContext
- 向 Master 注册 Application
- 启动 TaskScheduler/DAGScheduler
- 等待资源分配,提交任务
源码片段:
val sc = new SparkContext(conf)
流程图思路:
- 用户代码 → SparkContext → 注册 Application → 调度器就绪
口诀:
「Driver上线,Context先建,注册申报,调度开干」
6. Application 注册
关键流程:
- Driver 中 SparkContext 向 Master 注册 Application
- 通过 RpcEnv 发送
RegisterApplication
消息 - Master 记录 Application 信息,分配 ApplicationId
源码片段:
masterEndpoint.ask[RegisterApplicationResponse](RegisterApplication(...))
流程图思路:
- SparkContext → RegisterApplication → Master → ApplicationId
口诀:
「App先注册,Master记名,分配ID,资源分明」
7. Executor 生命周期
关键流程:
- Worker 启动 Executor
- Executor 注册到 Driver
- Executor 拉取任务并执行
- 任务完成后结果返回
- Executor 挂掉或被回收
源码片段:
// Worker 启动 Executor
val executor = new ExecutorRunner(...)
executor.start()
流程图思路:
- Worker → 启动 Executor → 注册 Driver → 执行任务 → 上报结果
口诀:
「Worker派遣,Executor上场,注册拉活,任务收场」
二、Shuffle 与调度系统
1. ShuffleReader 原理
作用:Task 拉取上游的 Shuffle 数据。
关键类/方法:
ShuffleReader
BlockStoreShuffleReader
IndexShuffleBlockResolver
源码片段:
val reader = new BlockStoreShuffleReader(...)
reader.read()
流程图思路:
- Task → ShuffleReader → Index文件定位 → 拉取数据块
口诀:
「Reader找索引,数据块定位,拉取无忧,结果送呈」
2. ShuffleTracker 机制
作用:管理 Shuffle 元数据,跟踪 Shuffle 状态。
关键类/方法:
MapOutputTrackerMaster
MapOutputTrackerWorker
源码片段:
tracker.getMapSizesByExecutorId(shuffleId, startPartition, endPartition)
流程图思路:
- Master 记录 Map 输出
- Worker 查询 Map 位置
- 拉取数据
口诀:
「Master登记,Worker查询,位置明了,数据随行」
3. 调度器Scheduler完整调度流程
关键类/方法:
DAGScheduler
TaskSchedulerImpl
流程:
- RDD action 触发 job 提交
- DAGScheduler 划分 Stage
- 提交 Stage,生成 TaskSet
- TaskSchedulerImpl 调度 TaskSet
- Executor 拉任务执行
源码片段:
// DAGScheduler 提交 job
submitJob(rdd, func, partitions, callSite, resultHandler, properties)
流程图思路:
- action → DAGScheduler → Stage划分 → TaskSet → TaskScheduler → Executor
口诀:
「Action触发,DAG分割,Task成组,Executor拿货」
三、RDD高级机制
1. RDD 持久化
作用:缓存中间结果,减少重复计算。
关键类/方法:
RDD.persist()
RDD.cache()
RDD.computeOrReadCheckpoint()
源码片段:
rdd.persist(StorageLevel.MEMORY_ONLY)
流程图思路:
- 调用 persist → 标记 StorageLevel → Executor 缓存数据
口诀:
「Persist标记,Level定级,Executor存,重用高效」
2. 检查点机制
作用:将 RDD 结果持久化到外部存储,断开血缘,容错恢复。
关键类/方法:
RDD.checkpoint()
RDD.isCheckpointed
源码片段:
rdd.checkpoint()
流程图思路:
- 标记 checkpoint → Job 触发 → 结果写到 HDFS → 更新血缘
口诀:
「Checkpoint标,执行写盘,血缘断裂,故障无难」
3. 广播变量
作用:全局只读变量,分发到每个 Executor。
关键类/方法:
SparkContext.broadcast(value)
Broadcast[T]
源码片段:
val bc = sc.broadcast(Array(1,2,3))
流程图思路:
- Driver注册变量 → Executor 拉取
口诀:
「广播Driver发,Executor自取,变量全局,效率无虑」
4. 累加器
作用:分布式聚合写变量,只能累加,不能读。
关键类/方法:
SparkContext.longAccumulator
AccumulatorV2
源码片段:
val acc = sc.longAccumulator("myAcc")
rdd.foreach(x => acc.add(x))
流程图思路:
- Driver 注册 → Task 分发累加 → Driver 汇总
口诀:
「累加驱动创,Task分布加,结果Driver收,聚合无差」
附:整体流程图思路
SparkSubmit↓
Driver (SparkContext)↓
注册 Application → Master↓
Master 分配资源 → Worker 启动 Executor↓
Executor 注册 Driver↓
DAGScheduler 划分 Stage → TaskScheduler 提交 TaskSet↓
Executor 拉取任务 → RDD 计算 → Shuffle 读写↓
结果返回 Driver
速记口诀总览
- RpcEnv:「Env搭桥,Endpoint通信,Ref发消息,Netty收听」
- Master:「Master起飞,Env先备,Endpoint就位,注册才对」
- Worker:「Worker启动,Env先行,Endpoint注册,资源上供」
- SparkSubmit:「Submit解析,模式选定,Driver启动,任务约定」
- Driver:「Driver上线,Context先建,注册申报,调度开干」
- Application:「App先注册,Master记名,分配ID,资源分明」
- Executor:「Worker派遣,Executor上场,注册拉活,任务收场」
- ShuffleReader:「Reader找索引,数据块定位,拉取无忧,结果送呈」
- ShuffleTracker:「Master登记,Worker查询,位置明了,数据随行」
- Scheduler:「Action触发,DAG分割,Task成组,Executor拿货」
- RDD持久化:「Persist标记,Level定级,Executor存,重用高效」
- 检查点:「Checkpoint标,执行写盘,血缘断裂,故障无难」
- 广播变量:「广播Driver发,Executor自取,变量全局,效率无虑」
- 累加器:「累加驱动创,Task分布加,结果Driver收,聚合无差」
如需进一步细化某个组件的源码细节、类图、时序图等,请告知!