核心概念

dozycat 的术语表与心智模型:dozycat、node、cat-agent、cat、volume、route,以及控制流与数据面如何协作。

一句话理解 dozycat

dozycat 是为成群的 microVM 提供的持久化 POSIX 文件系统。它构建在 JuiceFS 之上——对象存储作后端、高可用元数据引擎保证一致性、本地磁盘作缓存。它专为 git-on-disk + grep 这类工作负载调优:元数据密集、文件多在 1KB–1MB、读多写少、要求强一致。

关键设计:数据面与 VM 解耦。host 端跑 JuiceFS 客户端 + virtiofsd;guest(一个 Cloud Hypervisor microVM,我们叫它 cat)通过 virtio-fs 挂载文件系统。因此暂停、快照、迁移一个 cat 都不会中断 host 端向对象存储的上传——我们称之为「同步不停」。

术语表

概念含义
dozycat集中式控制面。提供 API + UI + CLI(三者同源),持有一份 registry(记录 node / cat / volume / route),编排 cat 的生命周期,并把执行计划派发到对应 node 上的 cat-agent。
node一台裸金属主机,运行一个 cat-agent。有容量、地址、状态,由 dozycat 注册并调度。
cat-agent每 node 一个的本机 agent。负责驱动 cloud-hypervisor / virtiofsd / 挂载 / drain,并暴露 HTTP 端点供 dozycat 派发执行。
cat一个 Cloud Hypervisor microVM。它冷热启停、挂载 dozycat、运行你的工作负载。
dozycat文件系统层本身:JuiceFS(对象后端 + 高可用元数据 + 本地缓存 + warmup 预热)。
volume一个 dozycat 文件系统实例。模型是每租户/每 VM 一个 volume。配额落在 registry:quota_gb(冷层总量)与 hot_gb(热缓存预算)。
route一个稳定的、与 VM 绑定的名字 xxxxx.dozyfs。无论 cat 当前落在哪个 node,这个名字与客户端连接方式永不改变。

为什么 VM 叫「cat」?

dozycat 面向「serverless 式」海量轮换——大量 VM 大部分时间在睡觉,只在被访问时醒来。这跟猫的作息很像,所以我们把每个 microVM 叫作一只 cat,并用猫咪状态映射它的生命周期:

猫状态VM 生命周期
工作 / 兴奋Running:活跃负载(兴奋态 = 高热 / warmup 中)
待机 idlehot-stop:VMM 暂停,内存快照已持久化到本地,可秒级热启
睡觉 sleepcold / deep-cold:已快照 / 无进程
跳 jumpActivating:cold-start 激活中

控制流:一个请求如何变成一只运行的 cat

客户端从不直接接触 node,所有编排都经过 dozycat:

client
  → dozycat(API / UI / CLI,三者同源)
      → registry(查/写 node · cat · volume · route)
          → 把 lifecycle 计划派发到目标 node 的 cat-agent
              → cat-agent 驱动 cloud-hypervisor 启动/恢复 cat
                  → cat 通过 virtio-fs 挂载 dozycat

每一步都对应 registry 里的一张表。dozycat 是唯一的真相源;cat-agent 只是执行端。

数据面:cat 的读写如何到达对象存储

数据面与控制面解耦,并且完全跑在 host 侧(这是「形态 B」):

cat(guest 内的 git / grep)
  ↕ virtio-fs
host virtiofsd
  ↕
host JuiceFS 客户端  ──(读缓存 + writeback 写缓冲在 host 本地盘)
  ↕
对象存储(S3 / GCS,权威持久层)
       +
高可用元数据引擎(inode / 目录树 / 锁 / chunk↔block 映射)

由于 JuiceFS 客户端与 virtiofsd 都是不会被 VM 冻结的 host 进程,暂停或快照一只 cat 不会停掉上传:

  • 凭证只在 host:guest 只看得到 virtio-fs,拿不到对象存储凭证。
  • FS 流量走 host 本地 socket,不占网络带宽。
  • 缓存可在同宿主多 cat 间共享
注意:可用性由元数据延迟决定,而非带宽——这正契合 git/grep「元数据密集、非海量读写」的画像。

稳定路由:xxxxx.dozyfs

每个 volume 在创建时获得一个确定性的永久名 xxxxx.dozyfs,与 volume 同生命周期、永不复用。一组固定的 anchor 网关接住所有 *.dozyfs 请求,查 registry 的 route 表,再反向代理到 cat 当前所在的 node。

  • 客户端永远连同一个地址——名字与连接方式不随 VM 迁移而变。
  • cold-start 到一个新 node 时,只重写绑定行(node_id / guest_ip),并令 activation_epoch + 1
  • 「来一个包就激活」:若目标 cat 处于 cold / deep-cold,网关先触发激活、等 ready,再代理。

可用 CLI 与 API 查看路由:

dozycat route ls
dozycat route get abcde12345.dozyfs

curl https://<control-plane>/api/routes/abcde12345.dozyfs

生命周期:冷热轮换

在规模下(约 1000 并发在线、10 万总量轮换),cat 在 hot↔cold 之间轮换以省成本。持久态都在 volume 里(对象存储),不在 VM 内存,因此内存快照只是性能优化、并非持久所必需。

状态含义激活延迟
Running活跃,占 CPU/RAM
hot-stop暂停(VMM 冻结、内存快照持久化到本地)亚秒级热启
cold已快照秒级
deep-cold无进程;请求 xxxxx.dozyfs 触发激活数秒~数十秒

每次降级前都会执行 drain:停收新写 → 等 writeback 暂存全部上行 + 元数据提交确认 → 才允许销毁/迁移,保证不丢写

dozycat 在 JuiceFS 之上只做四件事

dozycat 不重造文件系统。POSIX 语义、原子 rename、跨挂载锁、对象后端、缓存等都由 JuiceFS 提供。dozycat 只补上这四块:

  1. 热目录识别——判断哪个目录热(对象存储按 inode 数字命名,看不出路径热度)。
  2. VM 生命周期 drain——不丢写地停/迁移。
  3. 挂载 warmup 编排——按热度在工作负载跑起来前焐热缓存。
  4. 元数据引擎选型/运维 + 1000 节点控制面

想深入实现,请阅读仓库中的 DESIGN.mdgithub.com/dozycat/dozyfs