1 Ray 分布式计算核心概念
一句话定位:Ray 是面向 AI/ML 的分布式框架,用 Task/Actor 统一抽象 + Plasma 共享内存 + 细粒度动态调度,在异构资源(CPU/GPU)上跑 AI 数据处理与推理。面试核心是”为什么 AI 数据链路常比 Spark 更合适”。
2 整体架构:节点与核心组件
Ray 集群由若干节点组成,每个节点都有一个 Raylet(本地调度器)和 Object Store(基于 Plasma 的共享内存对象存储),集群层面还有全局的 GCS;Driver 是运行用户主程序的进程。
- GCS(Global Control Store):全局控制存储,保存系统级元数据——节点信息、对象所在位置、函数/类定义等;节点之间不直接互相通信,而是通过 GCS 共享状态,避免中心化调度器的单点瓶颈。
- Raylet:每个节点一个的本地调度器,负责资源管理、任务排队、依赖对象拉取与 Worker 生命周期管理,是”自底向上调度”的执行者。
- Worker 进程:真正执行 Task / 运行 Actor 的进程,按 CPU/GPU 资源需求由 Raylet 拉起,粒度可细到小数(如 0.3 GPU)。
- Object Store(Plasma):基于共享内存的本地对象存储,节点内零拷贝、节点间按需拉取。
3 Task(无状态)vs Actor(有状态)
- Task:
@ray.remote修饰的普通函数,无状态、输入→输出通过 ObjectRef 返回,调度器动态分配到空闲节点。适合无状态并行(map、批量推理)。 - Actor:
@ray.remote修饰的类,在固定节点上常驻一个进程、持有状态;其方法调用串行执行。适合有状态服务——参数服务器、模型推理服务、累积计数/状态机。 - 关键区别:Task 调用间不共享内存、可任意调度;Actor 把状态”钉”在节点上,调用有顺序保证但需考虑状态热点。
补充几点:
- Task 每次调用可能落在不同节点/Worker,函数本身不保存任何跨调用状态,返回值通过 ObjectRef 异步取回。
- Actor 创建后固定在某个节点,其方法(method)按提交顺序串行执行,天然避免并发写同一状态的竞态;若需并发,可用
AsyncActor(方法声明为async def)。 - 状态热点:所有调用都打到同一 Actor 进程,可能成为吞吐瓶颈,通常需要分片(多个 Actor 各持一部分状态)。
4 分布式对象存储 Plasma
- Plasma 是基于共享内存的分布式对象存储:大对象(DataFrame、模型权重、中间 tensor)以零拷贝方式在节点内/节点间传递,避免反复序列化拷贝。
- 对象由 ObjectRef 引用,生命周期由引用计数管理;这是 Ray 能在 Python 生态里高效搬运数据的基础。
- 生命周期细节:每个对象由创建它的进程(owner)负责,采用分布式引用计数(distributed reference counting),引用归零才回收——既避免跨节点大对象被过早释放,也不会内存泄漏。
- 跨节点语义:当任务依赖远端对象时,Raylet 会先把对象拉取(pull) 到本地 Object Store,之后本地 Worker 直接共享内存读取,避免反复走网络。
5 动态任务图调度
- 与 Spark 的”提交时静态 DAG”不同,Ray 的任务在运行时动态生成,调度器(全局 GCS + 局部)按资源可用性把细粒度 task 放到合适节点(可精确到 0.1 GPU)。
- 细粒度 → 更好的负载均衡与资源利用率,也天然支持不规则、依赖运行时的计算图。
自底向上(bottom-up)调度:Ray 没有全局中心调度器,而是由 Driver/Worker 把任务提交到本地 Raylet,本地 Raylet 先到 GCS 查输入对象在哪个节点,再决定在本地执行还是”转交”给持有数据的远端 Raylet。这种”数据/资源在哪里,就往哪里调”的方式既避免中心调度器瓶颈,又天然贴合数据本地性。
6 容错:基于血缘(Lineage)的重执行
- Ray 默认用血缘(lineage)记录任务依赖链(哪个对象由哪个 task 产生)。某个 task 或对象丢失时,调度器沿血缘重新执行上游 task 来重建,而不是像 Spark 那样依赖检查点快照。
- 对象重建:Plasma 中的对象若因节点宕机丢失,可从血缘重新计算得到。
- Actor 例外:Actor 是有状态长驻进程,无法简单”重执行”恢复,需要应用层通过 checkpoint 或重建 Actor 处理。这是 Ray 容错的薄弱点,也是面试常问的”Ray 容错边界”。
- 生产中可借助高层库(Ray Train / Ray Serve)的 checkpoint 机制增强容错。
7 面试重点:为什么 AI 数据链路 Ray 常优于 Spark
- 异构资源:Ray 原生细粒度分配 GPU(如 0.3 GPU 给算子 A、0.7 给算子 B);Spark 以 executor/core 粗粒度调度,GPU 支持弱。
- Python 原生:Ray 围绕 NumPy/PyTorch 设计,借助 Plasma 零拷贝传 tensor;Spark 以 JVM 为主,PySpark UDF 经 py4j 序列化开销大。
- 动态/细粒度调度:AI 管线常含 Actor 服务、动态 batch、运行期才确定的依赖,Spark 静态 DAG 不灵活。
- 典型场景:离线批量推理、超参搜索、RL、预处理+训练一体。
参考:
- 论文《Ray: A Distributed Framework for Emerging AI Applications》(Moritz et al., 2018, arXiv:1712.05889);
- Anyscale《Offline Batch Inference: Comparing Ray, Apache Spark, and SageMaker》








