Ray 是一个开源的统一分布式计算框架,起源于 UC Berkeley RISELab 的研究项目,由 Anyscale 公司主导开发与商业化。它解决的痛点很直接:Python 程序从单机扩展到集群的成本极高,而 Ray 让开发者只需在函数或类上加 @ray.remote 装饰器,任务调度、数据传输、失败重试、资源管理全部交由运行时自动处理,同一份代码可以在笔记本、单台服务器和上千节点集群之间无缝迁移。Ray 的独特之处在于围绕 AI 工作负载构建了完整组件栈——Ray Data 做分布式数据预处理、Ray Train 做分布式训练、Ray Tune 做超参搜索、Ray Serve 做在线推理、RLlib 做强化学习。目前 Ray 已被 OpenAI、Uber、Spotify、蚂蚁集团等公司用于生产环境,是 LLM 应用与大规模机器学习基础设施的事实标准之一。本篇攻略按“安装 → 上手 → 核心能力 → 生产部署 → 选型”的顺序组织,帮助你快速建立从 demo 到生产的完整路径。
对 AI 从业者来说,Ray 是把 Python 代码从单机原型推向集群生产的关键基础设施,掌握它意味着具备大规模训练、调参与推理服务化的核心工程能力。
目录
速览卡是工具类内容的固定首屏模块:30 秒判断「这工具是什么、能不能商用、适不适合我」。
为什么需要 Ray:Python 单机算力瓶颈与集群调度成本
Python 是 AI 与数据分析的事实标准语言,但单进程程序受 GIL 与单机 CPU 核数限制,无法充分利用多核与多机资源。传统扩展路径有两条:改用 Spark 等大数据框架,把逻辑改写成声明式 DataFrame API,代价是丢掉 Python 对象模型与丰富的库生态;或者自行搭建“多进程 + 消息队列 + 任务调度”系统,需要自己解决节点发现、网络通信、失败重试、资源分配等问题,工程量大且难以复用。
Ray 用两个最小原语解决上述问题:远程任务(Task)与远程类(Actor)。普通函数加 @ray.remote 装饰器即成为分布式任务,普通类加 @ray.remote 即成为跨节点可调用的有状态对象。任务调度、对象传输(共享内存零拷贝)、失败重试、资源调度均由运行时透明处理,开发者不需要维护节点列表或消息协议。同一份代码在本地 ray.init() 与多节点集群间无缝迁移,这是它区别于“分布式框架需要改架构”的传统印象的核心。
与 Dask、Spark 相比,Ray 的定位不是“数据分析框架”而是“通用 AI 运行时”:数据处理、训练、调参、推理由同一套分布式原语承载。这意味着团队只维护一条技术栈,数据预处理与模型训练之间不需要额外格式转换或数据搬运——这是它被 OpenAI、Uber、蚂蚁集团等采用的主要原因。
安装与环境配置:3 步就绪
步骤一·安装:要求 Python 3.8 以上(官方推荐 3.9-3.12)。建议先创建虚拟环境,再执行 pip install -U "ray[default]"。[default] 为必须的扩展标记,它会附带 Dashboard、客户端、参数服务等常用组件;只装裸 ray 包会缺少 ray start 的部分功能。
步骤二·验证:执行 python -c "import ray; print(ray.__version__)",能输出版本号即安装成功。若导入报错,优先检查 Python 版本与依赖冲突(常见于 grpcio 版本异常)。
步骤三·初始化:运行 ray start --head --port=6379 启动本地单机集群,终端会输出 Dashboard 地址 http://127.0.0.1:8265,浏览器打开可查看集群资源、任务时间线与 Actor 运行状态。开发调试阶段也可以直接在 Python 里调用 ray.init(),二者等效。
# 创建虚拟环境(推荐)python -m venv ray-env && source ray-env/bin/activate # 安装 Ray(含 Dashboard 等默认组件)pip install -U "ray[default]" # 验证安装python -c "import ray; print(ray.__version__)" # 启动本地集群,Dashboard 默认 http://127.0.0.1:8265ray start --head --port=6379 # 也可用官方镜像免安装体验(注意设置共享内存)docker run -it --shm-size=1g -p 8265:8265 rayproject/ray:latest
快速上手:10 分钟跑通并行任务与 Actor
最小可用流程只需一个 Python 文件:先验证远程任务并行加速,再验证 Actor 的有状态特性。整个流程不需要任何配置文件。
1. 新建 demo.py,在文件开头调用 ray.init() 初始化运行时;
2. 用 @ray.remote 装饰一个模拟耗时计算的函数,通过 compute.remote(i) 提交任务——注意 remote 调用立即返回、不阻塞;
3. 把多次提交返回的引用收集成列表,用 ray.get(futures) 一次性取回全部结果;
4. 再用 @ray.remote 装饰一个计数器类,实例化后通过 counter.inc.remote() 触发方法调用;
5. 运行 python demo.py,应依次输出 [0, 1, 4, 9] 和 [1, 2, 3]。
核心代码示例(与官方文档 API 一致):
进阶技巧:任务取消用 ray.cancel(ref);部分结果先到先用 ray.wait(futures, num_returns=1, timeout=...);小对象会自动内联在任务参数中,大对象才写入共享内存,无需手动管理序列化。
import rayimport time # 1. 初始化本地 Ray 运行时ray.init() # 2. 远程任务:函数加装饰器即可分布式执行@ray.remotedef compute(x: int) -> int: time.sleep(1) # 模拟 1 秒耗时 return x * x # 3. 并行提交 4 个任务,立即返回引用,不阻塞futures = [compute.remote(i) for i in range(4)] # 4. 一次性取回结果,总耗时约 1 秒而非 4 秒print(ray.get(futures)) # [0, 1, 4, 9] # 5. Actor:远程类实例,跨调用保留状态,方法默认串行@ray.remoteclass Counter: def __init__(self): self.n = 0 def inc(self) -> int: self.n += 1 return self.n counter = Counter.remote()print(ray.get([counter.inc.remote() for _ in range(3)])) # [1, 2, 3]
核心能力详解:5 大支柱
支柱一·Ray Core:分布式原语层。Task 是无状态远程函数,Actor 是有状态远程对象,ObjectRef 是对象引用——数据存放在共享内存中,多进程可零拷贝读取。调度、容错、资源上限(CPU/GPU/内存)都由这一层统一处理,是其余所有组件的运行时地基。
支柱二·Ray Data:分布式数据管道。可读取 Parquet、JSON、图片、文本等格式,map_batches、groupby、shuffle 等算子自动并行执行;与 Hugging Face Datasets 无缝衔接,能直接过渡到训练阶段,避免中间结果反复落盘。
支柱三·Ray Train:分布式训练。TorchTrainer、MegatronTrainer 等抽象封装了 DDP/FSDP 配置、checkpoint 保存与恢复、日志与指标聚合,从单卡扩展到多机多卡通常只需改一个配置对象,不用手写 init_process_group 等样板代码。
支柱四·Ray Tune 与 RLlib:调参与强化学习。Tune 提供 ASHA、BOHB 等调度算法做超参搜索,支持早停低效 trial;RLlib 内置 PPO、DQN、APPO 等策略算法与环境并行接口,适用于机器人控制、游戏 AI 等场景。
支柱五·Ray Serve:模型推理服务。用 Python 类定义模型部署,支持自动扩缩、多副本、金丝雀发布、流量分流与模型组合;兼容 FastAPI 接口,可直接把训练产物上线为 HTTP/gRPC 服务,是 LLM 应用在线化的常用层。
生产部署与监控:从上线到运维
部署方式一·Kubernetes(推荐):使用官方 KubeRay Operator,通过 RayCluster 自定义资源(CRD)声明集群规模、镜像与资源配额,KubeRay 负责 Pod 创建、扩缩容与故障自愈;作业通过 Ray Job 提交,支持排队与自动重试。这是当前生产环境的主流方式,适合已有 K8s 基础设施的团队。
部署方式二·裸机/云虚拟机:head 节点执行 ray start --head --port=6379,其余节点执行 ray start --address=<head-ip>:6379 加入集群。需打通节点内网并开放 6379(GCS 通信)、8265(Dashboard/Job API)、10001(Ray Client)端口。作业统一用 ray job submit --address http://<head>:8265 -- python train.py 提交,避免手工 ssh 分发代码导致版本不一致。
可观测性:Ray Dashboard 提供集群资源视图、任务/Actor 时间线与对象存储用量;ray status 命令行可查看各节点资源分配与排队情况;指标可接入 Prometheus/Grafana 做长期监控与告警。生产配置建议显式设置对象存储内存上限、容器 --shm-size,并用 OpenTelemetry 采集分布式追踪用于链路排查。
<p class="para-label">避坑清单:</p>
<ul class="dash-list"><li>大对象撑爆共享内存:对象存储默认占用物理内存的 30%,超限报 ObjectStoreFullError;用 ray.init(object_store_memory=……) 调大或分段处理,容器部署必须设置 --shm-size。</li><li>集群版本必须严格一致:GCS 协议不跨版本兼容,各节点 Ray 版本(含补丁号)不一致会导致加入集群失败或运行期异常,升级需全集群统一执行。</li><li>任务粒度过小反而更慢:每次远程调用有序列化与调度开销,毫秒级微任务并行收益为负;应放大任务粒度并批量用 ray.get 取回,避免循环内逐条提交。</li><li>GPU 任务必须显式声明:不写 num_gpus=1 时任务默认只申请 CPU,GPU 完全闲置;声明后还要确认节点 GPU 可用且显存未被占用。</li></ul>
| 维度 | Ray | Dask | Apache Spark | Celery |
|---|---|---|---|---|
| 定位 | 统一 AI 分布式计算平台 | 并行数据分析库 | 大规模批处理/数据湖引擎 | Web 异步任务队列 |
| 编排范式 | 任务 + Actor 两层原语 | 惰性计算图(Lazy DAG) | RDD/DataFrame 弹性数据集 | 消息队列 + 消费者 Worker |
| 类型约束 | 任意 Python 函数/类 | 任意 Python 函数;DataFrame 需 Dask 类型 | 需用 Spark API 改写 | 任意 Python 函数(无状态为主) |
| 学习曲线 | ★★★☆☆(中等) | ★★★☆☆(中等) | ★★★★★(较高) | ★★☆☆☆(较低) |
| 生态集成 | PyTorch/LLM/RL/推理原生组件 | NumPy/Pandas 生态与 HPC | Spark SQL/Java/Scala 生态 | Django/Flask + Redis/RabbitMQ |
| 生产部署 | KubeRay/K8s、Anyscale、裸机集群 | Helm、集群调度器、本地多进程 | YARN/K8s/独立集群 | 自建 Broker + Worker 组 |
| License | Apache 2.0 | BSD-3-Clause | Apache 2.0 | BSD-3-Clause |
| 适合谁 | AI/LLM 工程师、MLOps 团队 | 数据科学家的数组计算并行化 | 数仓工程师、离线 ETL | Web 应用后台任务开发者 |
选型建议:以 AI/LLM 为核心的团队选 Ray 最合适,它把数据、训练、调参、推理放在同一套运行时里,链路最短;纯数据科学计算并行化用 Dask 更轻量;已有 Hadoop 数仓、以 SQL/ETL 为主选 Spark;Web 后端只需要发邮件、图像处理等异步任务,Celery 足够。实际生产常混用——Spark 做离线 ETL,Ray 做训练与在线推理。
版本迭代
Ray 自 2017 年由 UC Berkeley RISELab 开源,2020 年 10 月发布 1.0 稳定版;2022 年 8 月的 2.0 是一次控制平面全面重写,把“分布式执行内核”升级为“AI 应用平台”;此后保持月度/双月发布节奏,重心转向 Data、Train、Serve 等组件的生产化(截至训练数据,可能已有更新版本)。
| 版本 | 时间 | 变化 | 提升 |
|---|---|---|---|
| 1.0 | 2020-10 | 首个稳定版 API | 任务/Actor 原语 API 冻结,提供生产可用承诺,社区生态快速成型 |
| 2.0 | 2022-08 | 运行时架构重写 | 统一控制平面、精简依赖,云原生部署(KubeRay)成为一等公民 |
| 2.4 | 2023-05 | Ray Data 新一代执行引擎 | Data 引入基于执行计划的流水线执行,Serve 增加部署串并联与 gRPC 支持 |
| 2.9 | 2023-12 | 稳定性与可观测性 | Dashboard 与 State API 增强,Train 检查点与故障恢复机制改进 |
| 2.20 | 2024-12 | 平台化与流式处理 | Serve 与 Ray Jobs 生产化增强,Data 对大规模流式数据的处理优化 |
| 2.24 | 2025-04 | 持续性能迭代 | 核心运行时与组件 bug 修复、训练与推理路径性能优化(截至训练数据,可能已有更新版本) |
Ray 的迭代主线是从“可用的分布式内核”走向“面向 AI 应用的完整平台”,Data、Train、Serve 三者协同是 2.x 中后期的重点。官方未发布跨版本的统一评测榜单,社区基准与生产案例显示 2.x 相比 1.x 在启动时间、数据流水线吞吐、Serve 扩缩规模上均有数量级提升。选型建议:生产环境至少使用 2.20 以上版本,并保持全集群版本一致。
AI 应用场景
大规模语料预处理与 RAG 流水线
阶段:RAG 管道构建 / 数据管道
解决的问题:构建检索增强生成(RAG)知识库需要清洗、分块、向量化百万级文档,单机串行需数天;Ray Data 将读取-清洗-分块-向量化整条流水线并行化,并可直接衔接 Ray Train 做模型微调,避免中间结果落盘与格式转换。
具体案例:一个 RAG 项目将数百万篇文档切分为亿级块并用 Embedding 模型批量向量化,使用 16 节点 Ray 集群后,流水线吞吐按节点数近似线性扩展,原本需数天的全量处理压缩到小时级;Hugging Face Datasets 与 Ray Data 的原生对接让预处理代码无需重写。
多模型统一在线推理服务
阶段:模型服务 / Agent 编排
解决的问题:生产中常同时部署多个模型(意图识别、向量化、主生成模型),各自起独立服务导致资源碎片化与管理混乱;Ray Serve 用 Python 类定义部署,路由、扩缩、版本灰度统一管理,并支持请求级批处理(batching)提升 GPU 利用率。
具体案例:某智能客服团队将意图分类、Embedding、LLM 生成 3 个模型统一部署在 Ray Serve 上,利用多副本自动扩缩应对高峰流量,通过金丝雀发布灰度新版本;Ray 官方生产案例(如蚂蚁集团金融风控场景)中,类似架构已支撑日亿级请求规模。
常见误区
误区只要给函数加上 @ray.remote 装饰器,程序就会自动并行加速,远程调用次数越多越好。
正解远程调用存在序列化、网络传输与调度开销:计算量只有几毫秒的微任务,并行收益会被开销抵消甚至变慢。正确做法是把任务粒度放大到秒级计算量,循环内逐条提交改为批量提交后用 ray.get 一次性取回,并用 ray.wait 处理部分完成的结果。
为何常见:Ray 的“把普通 Python 变成分布式”宣传让初学者忽略了分布式本身有通信成本,误以为装饰器是无代价的。
误区我在代码里调用了 ray.init(),生产环境里就能自动跨机器分布式运行。
正解不带参数的 ray.init() 只在当前机器启动运行时,用多个本地进程模拟并发,不跨节点。生产必须启动 head 节点、通过 ray start --address 或 KubeRay 组建集群,并用 ray.init("ray://<head>:10001") 连接真实集群做端到端验证。
为何常见:本地开发到生产的迁移过于顺滑(同一份代码无缝跑通),导致开发者误以为本地即集群,上线后才暴露网络与部署问题。
误区Actor 就是远程的普通对象,可以放进列表或参数里到处传、随便调。
正解传递的是 Actor handle(句柄)而非反序列化的对象副本;跨节点调用有网络成本,且同一 Actor 实例的方法默认串行执行以保证状态一致,并发热点会卡在单个 Actor 上。需要并发时应增加 Actor 副本数,无状态场景改用 Task。
为何常见:面向对象的直觉与“远程执行”语义存在落差,句柄与对象本体的关系容易被忽略。
误区head 节点用新版本、worker 用旧版本应该没问题,功能差不多就行。
正解Ray 要求集群内所有节点版本严格一致(包括补丁版本),GCS 协议与对象格式跨版本不兼容,混用会导致节点加入失败或运行期诡异错误。升级应全集群统一执行并做好回滚预案。
为何常见:日常 pip 依赖管理习惯是“各自环境各自装”,缺少对分布式协议一致性的认知。
误区有了 Ray,Spark 就该被淘汰,所有批处理都能用 Ray 做。
正解两者定位不同:Spark 强在 SQL、数仓 ETL、Java/Scala 生态与成熟的数据湖集成;Ray 强在 Python/AI 工作负载的一体化(数据→训练→推理)。结构化报表场景 Ray 并不比 Spark 有优势,生产常见做法是混用:Spark 做离线 ETL,Ray 做训练与在线推理。
为何常见:Ray 社区宣传常强调“Spark 替代”,叠加 AI 热潮,容易让从业者忽视工具的适用边界。
面试题
Q1. Ray 中将普通 Python 函数变成远程任务的标准方式是?
- A.给函数加 @ray.remote 装饰器← 正确答案
- B.继承 ray.Task 基类即可
- C.调用 ray.parallel 工厂
- D.在函数里调用 ray.init()
答案:A。@ray.remote 是官方定义的远程任务声明方式,调用时用 func.remote(……) 提交并返回 ObjectRef。B、C 是虚构 API;D 是初始化运行时,与“定义远程任务”无关。
Q2. 远程任务返回的句柄在 Ray 中称为什么?
- A.ObjectRef 对象引用← 正确答案
- B.FutureTask 句柄
- C.RayValue 存储指针
- D.RemoteData 包装对象
答案:A。task.remote() 立即返回 ObjectRef,它指向分布式对象存储中的数据,实际值需通过 ray.get(ref) 取回。FutureTask、RayValue、RemoteData 都不是 Ray 的公开概念。
Q3. 关于 ray.init() 的说法,正确的有?
- A.默认在本地启动运行时← 正确答案
- B.可传入集群地址连接远端← 正确答案
- C.同一进程内不可重复调用
- D.必须手动创建 Dashboard 服务
答案:AB。ray.init() 默认启动本地多进程运行时,也支持 ray.init("ray://head:10001") 连接真实集群;2.x 中重复调用会返回已存在的运行时上下文。Dashboard 由 ray start 或集群自动拉起,无需手动创建。
Q4. 下列哪个组件负责模型在线推理服务?
- A.Ray Serve 服务组件← 正确答案
- B.Ray Data 数据组件
- C.Ray Tune 调参组件
- D.Ray RLlib 算法组件
答案:A。Ray Serve 负责模型部署、扩缩、流量管理与灰度发布;Ray Data 是数据处理管道,Ray Tune 是超参搜索,RLlib 是强化学习算法库。
Q5. 任务需要使用 GPU 时应如何声明资源?
- A.在装饰器里声明 num_gpus=1← 正确答案
- B.任务能自动探测可用 GPU
- C.调用 ray.use_gpu 工具函数
- D.ray.get 传入 gpu 参数
答案:A。资源需求在装饰器中声明,如 @ray.remote(num_gpus=1);不声明则任务默认只申请 CPU,即使节点有 GPU 也不会分配。B、C、D 均不是官方机制。
Q6. Ray Actor 与 Task 的核心区别是什么?
- A.前者保留状态,后者无状态← 正确答案
- B.Actor 只能运行在 GPU 上
- C.Task 无法并行执行
- D.Actor 返回结果永远是列表
答案:A。Actor 是远程类的实例,跨方法调用保留实例状态且方法默认串行执行;Task 是无状态函数,每次调用独立调度。B、C、D 均为错误描述。
Q7. 关于 Ray 对象存储(ObjectRef 指向的数据),正确的是?
- A.需要开发者手动序列化存取
- B.大对象存储在节点的共享内存中← 正确答案
- C.所有对象都会落盘到本地磁盘
- D.对象只能被创建它的节点读取
答案:B。超过内联阈值的大对象写入共享内存(Plasma 对象存储),多进程可零拷贝读取;序列化由 Ray 自动处理,不要求手动管理,数据默认不落盘(除非显式配置持久化),对象可通过所有者机制跨节点传递。
Q8. 下列场景中最适合使用 Ray 而非 Spark 的是?
- A.训练时无缝衔接 PyTorch 与数据处理← 正确答案
- B.执行大规模的 SQL 报表查询
- C.处理海量结构化数据做长期 ETL
- D.提交 Java 打包好的批处理作业
答案:A。Ray 的核心优势是 Python/AI 工作负载一体化(Data→Train→Serve);Spark 在 SQL、离线 ETL、Java/Scala 生态上更成熟,B、C、D 都是 Spark 的舒适区。
Q9. Ray 生态中承担“训练与调参”职责的组件包括?
- A.Ray Train 训练组件← 正确答案
- B.Ray Tune 调参组件← 正确答案
- C.Ray Serve 服务组件
- D.Ray RLlib 强化学习← 正确答案
答案:ABD。Ray Train 提供分布式训练抽象(TorchTrainer 等),Ray Tune 做超参搜索与调度,RLlib 做强化学习训练;Ray Serve 只负责推理服务部署,不属于训练侧。
Q10. 生产环境排查 Ray 集群性能与资源问题时,正确手段有?
- A.ray status 查看资源现状← 正确答案
- B.查看 Dashboard 任务时间线← 正确答案
- C.用私有 API 读内存数据
- D.Prometheus 集成监控指标← 正确答案
答案:ABD。ray status 与 Dashboard 是官方提供的诊断入口,Prometheus/Grafana 集成是生产可观测的标准做法;C 中的“私有 API”并非官方公开能力,Ray 提供的是 State API 与 CLI 工具。
参考来源
- webpageRay 官网产品定位、生态介绍与客户案例