yuqi-zheng

Ray 核心架构:Task、Actor 与对象模型


本文是 Ray 源码解读系列的序章,介绍 Ray 的整体架构与核心设计理念,为后续深入各子系统打下基础。


1. API 理念与系统定位

Ray 提供三种核心抽象:Task(任务)、Actor(有状态工作进程)、Object(不可变值)。开发者用 Python 原生原语表达分布式逻辑,系统自动处理调度、内存、并行。

Ray 同时扮演”分布式胶水”的角色——可将 PyTorch、Dask、Modin 等不同框架组合在同一应用中。


2. 核心概念

概念说明
Task远程函数调用,无状态(@ray.remote 函数)或有状态(Actor 方法)。异步执行,返回 ObjectRef
Object不可变值,由任务返回或 ray.put 创建,通过 ObjectRef 引用。
Actor有状态工作进程(@ray.remote 类的实例),通过句柄提交任务,内部状态可修改。
Driver程序入口,运行 ray.init() 的进程。
Job从同一 Driver 递归产生的所有任务、对象、Actor 的集合。

3. 集群组件架构

┌─────────────────────────────────────────────────┐
│  头节点                                          │
│  ┌─────────────────┐  ┌──────────┐              │
│  │ GCS(全局控制)  │  │ Driver   │              │
│  └─────────────────┘  └──────────┘              │
├─────────────────────────────────────────────────┤
│  每个节点                                        │
│  ┌────────────────────────────────────────────┐ │
│  │ Raylet                                     │ │
│  │  ┌──────────────┐  ┌─────────────────────┐ │ │
│  │  │ 调度器        │  │ Plasma 共享内存      │ │ │
│  │  └──────────────┘  └─────────────────────┘ │ │
│  └────────────────────────────────────────────┘ │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐       │
│  │ Worker 0 │  │ Worker 1 │  │ Worker N │       │
│  └──────────┘  └──────────┘  └──────────┘       │
└─────────────────────────────────────────────────┘
  • Worker 进程:执行任务或 Actor 方法,持有所有权表与进程内小对象存储。
  • Raylet(每节点一个):调度器 + Plasma 共享内存存储。
  • GCS:集群级元数据管理(Actor 位置、节点成员等),Ray 2.0 支持 GCS 容错。

4. 所有权模型

Ray 采用去中心化元数据管理:每个 ObjectRef 由生成它的 Worker(Owner)负责管理。

Owner 职责:

  • 保证创建该对象的任务最终被执行
  • 解析 ObjectRef 到实际值
  • 管理引用计数与垃圾回收

优点:低延迟(约 1 RTT)、高吞吐(单客户端万级 tasks/s)、故障隔离自然。

限制:对象与 Owner 命运共享——Owner 死亡则对象不可访问;所有权不可转移。


5. 内存模型

类型说明
Worker 堆内存执行用户代码的常规堆内存
共享内存(大对象)ray.put 或任务返回的大对象,存于 Plasma,支持零拷贝读取、磁盘溢出
进程内存储(小对象)小于 100KB 的对象存在 Owner 堆内存中,读取时复制
Ray 元数据内存任务规格、引用计数等,每个活跃 ObjectRef 约占数 KB

6. 任务生命周期

  1. 提交:Owner 将参数打包为任务规格(小值内联,大值转 ObjectRef
  2. 依赖解析:Owner 等待所有 ObjectRef 参数就绪
  3. 资源调度:Owner 向分布式调度器申请资源
  4. 执行:调度器分配 Worker,Owner 通过 gRPC 发送任务规格
  5. 返回结果:小结果存 Owner 进程内存储;大结果存共享内存并通知 Owner 位置
  6. 错误处理:应用级错误(Python 异常)不重试;系统级错误(Worker 崩溃)可配置重试

7. 对象生命周期

  • 小对象(< 100KB):Owner 进程内存储,ray.get 时复制到请求方
  • 大对象:Plasma 共享内存,可零拷贝读取;需跨节点时由 Raylet 通过对象目录定位拉取

引用计数仅在两种操作时传递:将 ObjectRef 作为任务参数传递,或从任务返回 ObjectRef


8. Actor 生命周期

  • 创建:GCS 集中管理。创建者注册到 GCS,GCS 调度并启动 Actor 进程。
  • 执行:直接通过 gRPC 发送到 Actor,无需每次申请资源(资源在创建时已授予)。
  • 并发:默认串行;可选 asyncio 异步 Actor 或线程化 Actor。
  • 清理:普通 Actor 在创建者退出且无引用时自动清理;Detached Actor 需显式 ray.kill

9. 故障模型

系统级:除头节点外任意节点丢失不影响集群整体。GCS 通过心跳管理节点成员,超时节点标记为死亡。

应用级:任务与对象与 Owner 命运共享。可通过嵌套调用将不同子任务置于不同 Owner 下实现故障隔离。Detached Actor 可打破命运共享。

恢复选项:任务自动重试、Actor 自动重启、对象溢出(Spilling)、对象重建(Ray 2.0 默认启用)。


10. 语言运行时

Ray 核心以 C++ 实现,通过 CoreWorker 库统一底层。Python / Java / C++ 前端通过绑定调用 CoreWorker,由其负责所有权表、进程内存储、gRPC 通信。


后续文章将深入 Ray 的异步基础设施:instrumented_io_context、事件循环可观测性、线程池、gRPC 桥接与 GCS 线程隔离设计。