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. 任务生命周期
- 提交:Owner 将参数打包为任务规格(小值内联,大值转
ObjectRef) - 依赖解析:Owner 等待所有
ObjectRef参数就绪 - 资源调度:Owner 向分布式调度器申请资源
- 执行:调度器分配 Worker,Owner 通过 gRPC 发送任务规格
- 返回结果:小结果存 Owner 进程内存储;大结果存共享内存并通知 Owner 位置
- 错误处理:应用级错误(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 线程隔离设计。