Discard-Based Garbage Collection for Distributed Log-Structured Storage Systems in ByteDance (FAST 2026)
一句话总结:在字节 ByteStore + ByteDrive 的两层 append-only 存储栈里把 compaction-only GC 换成 discard + compaction 混合,针对高顺序写 + 频繁覆盖的 workload 把 write amplification 砍 25%、TCO 砍约 20%。
问题
ByteStore 是字节自研的 SSD-based 分布式 append-only 存储底座,承载 ByteDrive(块存储)、TOS(对象)、NAS、ByteGraph、ByteNDB 等服务。ByteDrive 把随机写转成 append-only 写到 LogFile,需要周期性 GC 回收 stale data。
原方案是 compaction-only GC:把 LogFile 里的有效数据搬到新 LogFile,然后删旧的。但这有一个根本权衡:
- 空间放大 vs 写放大负相关:激进 GC 降空间,但写放大暴涨 → SSD 寿命缩短 + 前台 I/O 抖动
- 量化代价:空间放大和写放大每月让 ByteDance 多花数百万美元 TCO
字节生产 trace 分析(online / SAR / offline 三类负载)发现 SAR(搜索/广告/推荐索引、AI 模型下载/推理)和 offline(Spark 等分布式计算)有强顺序写(>50% 写连续 >256 KiB)+ 秒级频繁覆盖,导致 LogFile 上出现长连续的 stale 区段。这种 garbage 用搬数据的 compaction 处理纯属浪费。
核心方法
DisCoGC = Discard + Compaction 混合 GC。Discard 直接释放 LogFile 上 stale range 占的物理空间,不搬有效数据。架构上 discard 自顶向下穿透 Volume / Segment / LogFile / UFS(自研 ChunkServer 上的 Userspace-Filesystem)四层,但有四个挑战要解:
- Boundary loss(边界丢失):层间 allocation unit 不对齐(EC stripe vs cluster vs 4 KiB 块 + sector header 32 B / 4064 B data),discard 范围两端凑不齐对齐单元就丢空间。
- Boundary extension:新 discard 范围向已 discard 的相邻范围多伸几 MiB 重叠回收边界
- Discard-friendly EC stripes:把 EC stripe unit 配成
n × 4 × 4064 B与 cluster 对齐
- MetaPage 更新开销:每次 discard 都要改 UFS MetaPage 写 SSD + 占 CPU
- 对同一 LogFile 的 discard 请求做 batching + 限制 discard 并发/IOPS
- LogFile/chunk 碎片化 → metadata 膨胀:定期跑 compaction 合并碎片
- SSD trim IOPS 受限:SSD 不及时回收 → 内部 GC 激进 → 前台抖动
- Trim filter 优先大范围 trim
- Trim merger 把小 trim 合成大 trim,更省 SSD 的 trim IOPS 预算
关键结果
- 生产集群(混合负载):空间放大降 10% 同时 write amplification 降 25% → TCO 降约 20%
- 高顺序写 + 频繁覆盖(SAR/offline 类):TCO 降 >25%
- 随机/碎片化负载(online 类):TCO 也降 2-5%(鲁棒性 OK)
- 性能无回退(latency 不增)
- 给出 deployment guideline:先看 trace 顺序性 + 覆盖率决定是否启用 DisCoGC