Persisting(Pulsing Queue)vs TransferQueue 打分点评
基于接口对比与性能分析文档的维度,对两者做 1~5 分打分(5 为优),并附简短点评。
说明:Persisting 侧指「Persisting Queue + Pulsing 分布式 + Lance 后端」这条链路;TransferQueue 指官方默认配置(Ray + Controller + SimpleStorage / 可选多后端)。
1. 打分总表
| 维度 |
Persisting (Pulsing Queue) |
TransferQueue |
说明 |
| 定位与场景匹配 |
4 |
5 |
见下 |
| 架构与扩展性 |
5 |
3 |
见下 |
| 存储与持久化 |
5 |
3 |
见下 |
| API 易用性 |
3 |
5 |
见下 |
| 读路径与延迟 |
5 |
3 |
见下 |
| 大 tensor / 吞吐潜力 |
4 |
5 |
见下(含补充说明) |
| 生态与成熟度 |
3 |
5 |
见下 |
| 可维护性 / 可插拔 |
4 |
5 |
见下 |
| 综合 |
4.1 |
4.3 |
加权平均(维度等权) |
2. 分维度点评
2.1 定位与场景匹配
| 项目 |
分数 |
点评 |
| Persisting |
4 |
定位清晰:分层存储 + TTAS 寻址,Queue 作为「流式追加 + 顺序扫描」的一种访问形态;与 KV Cache / 参数 / 轨迹的路线图一致。队列本身是子模块,不是唯一主角,故在「纯队列场景」的叙事上略逊于 TQ。 |
| TransferQueue |
5 |
目标单一且对准后训练:数据网关、生产/消费解耦、细粒度样本状态、与 verl 等集成。文档、教程、高层 KV / StreamingDataLoader API 都围绕该场景,匹配度高。 |
2.2 架构与扩展性
| 项目 |
分数 |
点评 |
| Persisting |
5 |
分布式时无中心 Controller;按 topic + bucket 分散到多个 BucketStorage,读写均可多路并行。多消费者用 rank/world_size 分 bucket 即可线性扩展。 |
| TransferQueue |
3 |
Controller 单点:get_meta、状态、Sampler 均经其过,高 QPS 时易成瓶颈。写可直连多 Storage 单元,但 get_meta 扩展性受限于单 Controller,需后续分片/多副本才能拉高。 |
2.3 存储与持久化
| 项目 |
分数 |
点评 |
| Persisting |
5 |
队列默认 Lance 列存落盘;Agent 轨迹 canonical 为 Lance(events.lance/ 目录),队列与 capture 均天然持久化,适合复现、审计与故障恢复。 |
| TransferQueue |
3 |
默认 SimpleStorage 为内存;持久化依赖可选后端(Yuanrong、Mooncake 等)。能力有,但非默认开箱即用,需选型与配置。 |
2.4 API 易用性
| 项目 |
分数 |
点评 |
| Persisting |
3 |
Queue 语义简单(put/get/flush),但 KV 与 Tensor 能力在 KVInterface + put(partition_id) 等,需理解 Queue 与 KV 两层。分布式需先有 Pulsing 环境,学习路径略长。 |
| TransferQueue |
5 |
高层 KV(kv_put / kv_batch_get / kv_list / kv_clear)与 StreamingDataLoader 开箱可用;init/close 一次,全局 tq.xxx 调用,对「后训练脚本」非常友好。低层 get_meta + get_data 可选。 |
2.5 读路径与延迟
| 项目 |
分数 |
点评 |
| Persisting |
5 |
一次 reader.get(limit) 直连 BucketStorage,单 RTT 取数据,小 batch、延迟敏感场景更优。 |
| TransferQueue |
3 |
get_meta(Client → Controller)+ get_data(Client → Storage)两跳,多一轮 RTT;换来的「先看元数据、按需拉字段」在简单读批场景用不上时等价于额外延迟。 |
2.6 大 tensor / 吞吐潜力
| 项目 |
分数 |
点评 |
| Persisting |
4 |
分布式时可走 Pulsing 的 zero-copy 传输(zerocopy_mode / __zerocopy__ 协议),大 buffer 走 descriptor + 裸数据块,避免 pickle 与多余拷贝;Lance 落盘后大块不反复经网络也是优势。 |
| TransferQueue |
5 |
TensorDict + 定制序列化 + ZMQ copy=False、大 socket 缓冲,零拷贝与高带宽潜力明确,适合大 batch、高吞吐 tensor 流。 |
2.7 生态与成熟度
| 项目 |
分数 |
点评 |
| Persisting |
3 |
无独立论文;与 Pulsing 绑定,文档偏架构与设计,示例和社区可见度尚在建设中。 |
| TransferQueue |
5 |
有论文(AsyncFlow)、verl 集成、多后端、教程与博客完整,社区与迭代可见度高。 |
2.8 可维护性 / 可插拔
| 项目 |
分数 |
点评 |
| Persisting |
4 |
后端通过 Pulsing 的 register_backend 可插拔,Lance 与 Persisting 职责清晰;Queue 与 KV 分层清楚,但分布式依赖 Pulsing,可插拔范围在「存储后端」而非「控制面/传输栈」。 |
| TransferQueue |
5 |
存储 Manager + Client 工厂、多后端(SimpleStorage、Yuanrong、Mooncake、Ray 等)、Sampler 可定制,配置化与扩展点完整,可维护性与可插拔性都很好。 |
3. 场景化推荐(一句话)
| 场景 |
更合适的一侧 |
| 后训练流水线、与 verl 等集成、要开箱即用高层 API |
TransferQueue |
| 需要默认持久化、轨迹/事件落盘、复现与审计 |
Persisting |
| 多客户端高 QPS、希望无单点、水平扩展简单 |
Persisting(Pulsing) |
| 大 tensor、高带宽、零拷贝与吞吐优先 |
TransferQueue(或 Persisting + Pulsing zerocopy) |
| 既要持久化又要 TQ 风格 API |
Persisting Queue + KVInterface,或 TQ + 持久化后端 |
4. 总结
- TransferQueue 在「后训练数据网关」这一垂直场景上更成熟:API 友好、生态完整、大 tensor 与吞吐潜力强;代价是 Controller 单点与读路径多一跳,以及默认不落盘。
- Persisting(Pulsing Queue) 在架构扩展性、默认持久化与读延迟上占优,且分布式仍统一用 Lance Backend;API 与生态相对更偏「存储与运行时」的基建视角,需要一定集成与学习成本。
若在 Persisting 上进一步补齐高层 API 与文档(如一键 KV 入口、无 Pulsing 的本地用法示例),综合分数会向 TQ 靠近;分布式下已可通过 Pulsing zerocopy 提升大 tensor 吞吐(见下方补充说明)。
5. 补充说明
-
Persisting 可走 Pulsing 的 zero-copy 传输:分布式模式下,Queue 创建 writer/reader 时传入 backend_options={"zerocopy_mode": "auto"}(或 "force"),数据经 Pulsing Actor 传递时可走 __zerocopy__ 协议:payload 以 descriptor + 裸 buffer 形式传输,避免 pickle 与整块内存拷贝,大 tensor 场景下与 TQ 的 ZMQ 零拷贝路径可比。需发送端类型实现 __zerocopy__(或使用已支持的 tensor/buffer 封装)。
-
KV 接口的意义与定位:纯队列是「按顺序 append、按 offset 消费」,无法按业务主键访问。KV 接口(Put/Get/List/Clear by key + partition)在概念上提供:(1)按 key 寻址;(2)按 key/列细粒度读写;(3)key 级 tag 与状态追踪;(4)Redis 风格抽象。实践中该接口往往偏低频、偏鸡肋:多数后训练/流水线场景以「流式生产 + 按批消费」为主,顺序 get(limit) 或 Sampler 拉批即可满足,按 key 随机访问、kv_list/kv_clear 等用到的机会不多;若只在少数环节需要「按 id 查一条」,应用层在 record 里带 id 再过滤也能解决。因此 KV 更适合视为兼容层或可选能力(对齐 TQ 高层 API、迁移平滑),而非核心卖点;Persisting 用 KVInterface 薄层实现即可,不必在存储或控制面上过度投入。