一个简单的提问
Cloudflare Workers 的 Durable Objects 是过去十年最优雅的后端抽象之一:每个"对象"是一个有状态的实体,有自己的 SQLite 数据库,单写入者保证,自动复制,按需休眠。用它写多人协作应用、实时游戏、会话管理,代码量比传统方案少一个数量级。
但它被锁在 Cloudflare 的基础设施里。
Deno 团队(对,就是那个 Deno)的回答是:celld——一个开源 daemon,让你在自己的机器上、自己的 S3 bucket 上,跑 Cloudflare Workers 和 Durable Objects 的代码。单日 GitHub 涨 546 stars。
核心设计:bucket 就是协调器
celld 最反直觉的设计决策是这一句:
没有控制平面,没有共识服务,没有成员协议。节点之间只通过一个 S3-compatible bucket 协调。
传统分布式系统的做法:Raft/Paxos 共识、Gossip 成员协议、故障检测器、leader 选举。celld 全部砍掉。
它的做法:
- 每个 cell(Durable Object)是一个 SQLite 数据库
- 节点通过 bucket 里的 compare-and-swap 原子写获取 cell 的 ownership lease
- 同一时刻只有一个节点 own 一个 cell——不需要共识协议保证
- cell 的 SQLite 状态以 LTX segments 持续复制到 bucket
- 节点挂了,另一个节点 acquire lease,从 bucket 恢复 SQLite,继续执行
bucket 是唯一的事实来源,节点是可替换的。
这让我想到一个类比:celld 是 Durable Objects 版的 Git。Git 把代码仓库的真相放在 .git 目录里,工作区只是 checkout;celld 把 cell 状态放在 bucket 里,节点只是 runtime。Git 的节点(开发者机器)可以随时挂掉、换新,只要 .git 在,代码就在。celld 的节点也一样,只要 bucket 在,cell 就在。
性能数据:为什么这不是玩具
celld.dev 官网给出的基准数据:
| 指标 | 数值 |
|---|---|
| 持久写入延迟(region-local) | ~90 ms |
| RPO(recovery point objective) | 0 |
| 无状态请求 p50/p99 | 0.2/0.3 ms |
| 无状态吞吐/worker thread | ~94k req/s |
| 唤醒休眠 cell | ~4 ms |
| 每 resident cell 内存 | 4 MB |
| 8GB 节点 resident cells | 1,000 |
| 非活跃 cell 成本 | ~0 |
| 节点故障 failover | ~20 秒,0 丢失 |
这些数字里最值得注意的两个:
94k req/s per worker thread——这是无状态请求的吞吐,意味着 celld 的 V8 runtime 没有成为瓶颈。
4 MB per resident cell——1,000 cells 在 8GB 节点上。对比 Cloudflare 自己的 Durable Objects 定价:\(4.15/resident-cell-month。1,000 cells 在 Cloudflare 上是\)4,150/月,在 celld 上是一个 \(48/月的 8GB DigitalOcean droplet。**85 倍成本差**。 ## 成本曲线:为什么规模越大越划算 celld.dev 给了一张图,核心数据: | Resident cells | Cloudflare DO | celld | |---|---|---| | 10 |\)42/mo | \(49/mo | | 100 |\)415/mo | \(49/mo | | 1,000 |\)4,150/mo | \(49/mo | | 10,000 |\)41,500/mo | \(486/mo | | 100,000 |\)415,000/mo | $4,856/mo |
10 个 cells 以下,Cloudflare 更便宜(有免费额度)。100 个 cells 以上,celld 的成本优势指数级扩大。100,000 cells 时,celld 比 Cloudflare DO 便宜 85 倍。
这不是 celld 更聪明,是定价模型不同。Cloudflare 按 resident-cell-month 计费,celld 按"你自己的 VM"计费。VM 的成本是固定的,cells 越多摊得越薄。Cloudflare 的成本是线性的,cells 越多花得越多。
压力 shedding:当节点装不下
celld 的另一个设计亮点是压力 shedding。当节点内存或 CPU 紧张时:
CELLD_MAX_RESIDENT_CELLS=1000 \
CELLD_RESIDENT_LOW_WATER=800 \
celld --bucket s3://my-cells-bucket
节点会在高水位时把 LRU 的 idle cells 持久化、fence、发布为 unowned;在低水位前不再 acquire 新的 unowned cells。有活跃工作或 live WebSocket 的 cell 不会被 shed。
这个设计的关键约束:shedding 不是失败,是正常调度。cell 的状态已经持久化到 bucket,shed 后另一个 spare 节点会通过同样的 bucket 协议 acquire 它。对用户来说,这看起来就像一次普通的 cell 迁移。
对比传统数据库的 OOM:数据库内存满了就是满了,要么拒绝写入要么 crash。celld 的 shedding 是把"内存满了"变成一次可逆的调度决策。
为什么 Deno 团队做这个
Deno 团队做 celld 不是偶然。Deno 本身就是"V8 runtime + Rust"的组合,celld 也是"V8 runtime + Rust"。Deno Deploy 是 Cloudflare Workers 的竞品,但 Deno Deploy 是托管服务,celld 是自托管版。
这背后的判断是:2026 年的开发者不满足于"托管 PaaS",他们想要"开源 PaaS"。Cloudflare Workers 的编程模型(Workers + Durable Objects)已经被证明优秀,但不是所有人都想被锁在 Cloudflare 的基础设施和定价里。celld 把同样的编程模型开源,让你可以在任何 S3-compatible storage + 任何 VM 上跑。
这是"编程模型"和"基础设施"的解耦。Cloudflare 发明了 Durable Objects 这个抽象,celld 把它变成公共品。
一个值得深想的问题
celld 的"bucket 作为协调器"设计有一个隐含假设:S3-compatible storage 是可靠的。如果你的 bucket provider 挂了,整个 fleet 就挂了。
Cloudflare 的 Durable Objects 不依赖外部 storage——它的存储和计算在同一基础设施里,由 Cloudflare 内部保证一致性。celld 把这个保证外包给了 S3。
这意味着:celld 的可靠性上限 = 你的 bucket provider 的可靠性。如果你用 AWS S3,那是 99.999999999% 的 durability(11 个 9)。如果你用 MinIO 自建,那就是你自建的水平。
celld 把"分布式系统的复杂性"换成了"对外部存储的信任"。这是一个聪明的 trade-off——大多数团队管理 S3 比管理 Raft 共识容易得多。但它也意味着 celld 不适合所有场景,特别是那些连 S3 都不想信任的场景。
链接
- GitHub: https://github.com/denoland/celld
- 官网: https://celld.dev
- 文档: https://celld.dev/docs
一句话总结:celld 把 Cloudflare Durable Objects 的编程模型开源了——bucket 当协调器,SQLite 当状态,V8 当 runtime。100,000 cells 时比 Cloudflare 便宜 85 倍。
讨论回复
加载中...正在加载回复...
推荐
智谱 GLM-5 已上线
我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。