腾讯云 x JuiceFS:基于 FoundationDB 的企业级统一存储实践

发布时间:2026/8/1 14:43:27
腾讯云 x JuiceFS:基于 FoundationDB 的企业级统一存储实践 随着大数据和 AI 业务发展越来越多企业开始从存算一体架构转向存算分离架构。但在实际落地中企业往往同时使用 COS、OBS、S3、HDFS 等多类存储系统不同后端在协议、鉴权、文件系统语义和元数据性能上存在差异给统一接入、数据利旧和缓存加速带来了挑战。针对这些问题腾讯云团队基于 JuiceFS FoundationDB 构建了一套企业级统一存储方案既能为新建文件系统提供完整的 POSIX 语义也能将已有对象存储和 HDFS 数据纳入统一命名空间实现存量数据的统一访问与缓存加速。其中FoundationDB 作为元数据引擎支撑百亿级元数据管理和强一致事务这也是 JuiceFS 社区首次分享将 FoundationDB 用于元数据管理的实践本地缓存与分布式缓存则用于降低远端访问延迟。后续团队还将围绕湖仓一体、AI 训练加速、智能分层和跨集群联邦等方向持续演进。01 背景与挑战存算分离之后存储接入变复杂了在前期客户沟通和 POC 过程中我们发现企业从存算一体迁移到存算分离时最关注的并不是架构形态本身而是两个更实际的问题现有数据和业务能否平滑接入切换后性能是否还能接近原有存算一体架构。企业往往同时使用 COS、OBS、S3、HDFS 等多类存储系统。不同后端在访问协议、SDK、鉴权方式和文件系统语义上存在差异如果 Spark、Hive、Flink 或 AI 训练框架需要分别适配客户端开发和维护成本会迅速上升。性能也是存算分离落地中的关键挑战。数据访问路径变长后远端存储和网络访问会引入额外开销而多存储并存又使缓存能力难以统一复用。因此统一存储方案不仅要解决多后端接入问题还要提供可复用的缓存加速能力。此外对象存储虽然适合海量数据存放但在list、stat、目录遍历和小文件访问等元数据操作上通常不如传统文件系统高效不同后端对目录、权限、配额和快照等语义的支持也并不一致这些差异会进一步影响大数据和 AI 应用的统一访问体验。基于这些需求我们最终选择以 JuiceFS 构建面向企业场景的统一存储方案。02 整体架构统一接入与双模式设计JuiceFS 采用元数据与数据分离的架构。元数据引擎可以根据业务规模和一致性需求进行选择例如 Redis、TiKV 等我们选择 FoundationDB主要利用其强事务、有序 Key-Value、自动数据分布和横向扩展能力支撑百亿级元数据管理。基于 JuiceFS 的基础架构我们构建了由统一客户端、服务化元数据层、多级缓存和多后端存储适配组成的统一存储方案。JuiceFS 提供文件系统语义、多协议访问、对象存储数据路径和本地缓存等基础能力在此基础上我们进一步扩展统一鉴权、多卷管理、统一命名空间、已有数据接入和分布式缓存等能力以满足云服务场景下的多租户和多存储需求。在客户端侧大数据和 AI 应用可以通过 HDFS 接口、POSIX 挂载、S3 接口和 Python SDK 等方式访问系统。客户端支持 Hadoop SDK、Python SDK、FUSE 挂载、本地缓存和服务发现使 Spark、Hive、Flink、Presto 以及各类 AI 训练框架无需分别适配底层存储。在元数据访问路径上我们将 JuiceFS 的元数据访问链路服务化。客户端不直接连接 FoundationDB而是通过 RPC 与无状态元数据服务交互。元数据服务统一承载元数据 API、认证鉴权、多卷管理、配额管理、目录保护、文件保护和任务管理等能力并通过 ZooKeeper 完成服务注册、服务发现和跨节点状态同步。元数据服务可以按需水平扩展FoundationDB 则作为其后端元数据引擎负责元数据持久化和事务处理。为了同时覆盖新建文件系统和已有数据接入场景底层存储层提供托管模式和外部模式。托管模式主要面向新建文件系统。文件元数据通过元数据服务写入 FoundationDB文件数据按照 JuiceFS 的chunk / slice / block模型切分后写入对象存储从而提供完整的 POSIX 文件系统语义。外部模式主要面向已有数据利旧场景其核心是 UFSUnified File System抽象层。UFS 将 COS、OBS、S3 和 HDFS 等后端抽象为统一的文件系统接口但不迁移或接管后端已有的数据和元数据也不使用托管模式的切片存储路径。元数据类请求由元数据服务通过 UFS 透传到底层存储数据读写则通过相应后端的原生协议完成。统一命名空间将两种模式组织在同一套目录结构中。对上层应用来说看到的是统一的路径和访问入口对底层实现来说不同目录既可以对应托管文件系统也可以挂载已有的 HDFS 或对象存储数据。这样新增数据与存量数据可以在同一套访问体系下共存而无需先完成大规模数据迁移。在数据访问路径上系统同时提供本地缓存和分布式缓存。读请求优先查询本地缓存本地未命中后访问分布式缓存最后再回源到底层存储从而降低远端访问延迟和后端存储压力。03 FoundationDB 实践面向百亿级元数据的设计取舍在统一存储接入层中元数据引擎决定了系统的规模上限和一致性能力。当文件数量达到十亿甚至百亿级时元数据系统本身就会成为整个架构的关键瓶颈。为什么选择 FoundationDB在元数据引擎选型阶段我们重点关注几个问题单集群是否能够支撑百亿级元数据规模事务模型是否足够强是否支持自动分片和横向扩展以及运维复杂度是否可控。传统关系型数据库在单卷规模和横向扩展上容易遇到瓶颈因此我们重点评估了分布式 KV 方案其中也包括 TiKV 和 FoundationDB。TiKV 在行业内已有不少大规模元数据场景实践也具备较强的横向扩展能力FoundationDB 则在严格事务一致性、有序 Key-Value 模型、自动数据分布、多副本强一致以及运维复杂度方面更符合我们的需求。最终我们选择 FoundationDB 作为元数据引擎主要是因为它更适合承载文件系统元数据这类强一致、高并发、可范围扫描的访问模式。与此同时这次实践也让团队积累了 FoundationDB 在大规模元数据场景下的建模、调优和运维经验为后续 Hive 库表元数据等更多场景提供了参考。Key 设计多卷隔离与范围扫描文件系统元数据天然具有两类访问特点一是同一集群需要承载多个文件系统要求不同卷之间有清晰边界二是目录遍历、属性查询、chunk 索引查询等操作经常依赖前缀扫描。因此Key 设计既要满足多卷隔离也要尽量贴合文件系统的访问路径避免在大规模场景下引入热点或大事务问题。基于 FoundationDB 的有序 KV 特性我们延续了 JuiceFS 元数据设计思路以fsname作为 Key 前缀区分不同文件系统将同一文件相关的属性、目录项、chunk 索引等元数据组织在相近 Key 空间内提升访问局部性数值字段采用大端序编码使字典序与数值顺序保持一致便于顺序扫描。在此基础上多个文件系统可以共用同一个 FoundationDB 集群同时保持各自独立的 Key 空间。对于list等可能扫描大量数据的操作则通过分页处理控制单次事务规模事务冲突场景下结合乐观锁和自动重试减少锁等待。如何规避 FDB 的硬限制FoundationDB 对 key、value 和事务大小都有明确硬限制单个 key 最大 10KB单个 value 最大 100KB单个事务总大小最大 10MB。这些限制不能通过参数调整因此在将其作为文件系统元数据引擎时需要特别关注几类容易放大元数据规模的操作例如频繁随机写、反复 truncate、fallocate punch hole、copyFileRange 等可能导致单个 value 持续增长大范围文件拷贝、大文件截断、批量元数据导入或删除整个文件系统则可能触发事务过大的问题。其中风险最高的是 chunk slices 累积。在 JuiceFS 的数据模型中一个 chunk 对应的 slice 列表会存储在同一个 value 中每个 slice 约占 24 字节。当同一个 chunk 下累积到约 4,266 个 slices 时就可能触及 FoundationDB 的 100KB value 限制。频繁随机写同一个 chunk、反复 truncate、fallocate punch hole、copyFileRange 等操作都会持续增加 slice 数量。如果缺少治理机制单个 value 就可能不断膨胀最终导致事务提交失败。这个问题在实现上还有一个隐蔽点部分路径会使用AppendIfFits这类原子追加操作。它属于盲写事务内无法提前知道 append 之后的 value 总大小如果 append 后超过 100KB往往要到事务提交阶段才会失败。这意味着问题不会在写入前及时暴露而是随着 slice 静默累积在某次提交时突然触发。因此仅依赖失败后的重试并不够还需要在数据模型和写入路径上提前设置安全边界。为了解决 chunk slices 累积问题我们补齐并强化了 compact 机制。核心思路是在读写路径中提前发现 slice 数量过多的 chunk并将多个小 slice 合并为更少的大 slice从而控制单个 value 的增长。对于轻度碎片化的 chunk可以异步触发 compact避免阻塞正常写入当 slice 数量达到安全阈值时则同步触发 compact防止继续增长到 100KB 限制。实践中maxSlices设置为 2500对应约 60KB为 100KB 上限预留了约 40KB 的安全空间。在实现 compact 时还需要处理并发和回收问题。合并过程通过 CAS 语义确认 chunk 没有被并发修改避免数据丢失如果 compact 失败不影响正常写入可以在后续触发时重试。合并后产生的旧 slice 则进入 GC 流程通过引用计数判断是否仍被使用并结合延迟删除机制支持误删恢复和后台回收。除了 chunk slices 累积我们也排查了文件系统配置、Kerberos Token、POSIX 锁、Xattr 扩展属性以及 UFS 路径类 key 等其他风险项。整体来看这些风险相对可控大部分 value 规模较小key 设计也受到文件名或路径长度约束。真正需要重点治理的仍然是 chunk slices 累积导致的单 value 膨胀问题。04 缓存加速体系用两级缓存降低远端访问开销存算分离之后数据访问路径从本地磁盘变成了远端对象存储或 HDFS。对于大数据分析和 AI 训练这类读密集场景如果每次读取都直接回源到底层存储网络延迟和后端访问压力都会被放大。因此统一存储层除了要解决“如何接入多种存储”还需要解决“如何让远端数据读得更快”。我们的思路是引入两级缓存客户端本地缓存作为 L1分布式缓存作为 L2。读请求会先查询本地缓存命中后直接返回本地未命中时再访问分布式缓存如果分布式缓存仍未命中才回源到底层存储并将数据回填到缓存体系中。这样既能利用客户端本地 SSD 或内存提供最低延迟也能通过独立的 SSD 缓存集群在多个客户端之间复用热点数据。本地缓存主要沿用 JuiceFS 社区已有能力并扩展支持外部模式。它运行在客户端进程内默认以 block 为粒度缓存数据支持 LRU 淘汰、顺序读预取和 OS Cache 控制。分布式缓存则是我们自研的独立缓存集群客户端通过一致性哈希将相同数据块路由到固定缓存节点更适合多节点共享读、客户端本地空间有限或者需要跨任务复用热点数据的场景。缓存体系真正需要重点处理的是一致性。托管模式下每次写入都会生成新的 Slice ID缓存 key 随之变化旧缓存自然不会被再次命中同时对象存储中的底层对象写入后不会被原地修改因此不需要额外的主动失效机制。外部模式则更复杂因为底层 HDFS 或对象存储中的文件可能被外部系统直接覆盖。如果缓存 key 只包含路径就可能读到旧数据。为此我们在外部模式中引入 fingerprint 机制将文件路径、block 偏移以及文件指纹一起纳入缓存 key。fingerprint 由文件修改时间和长度组成并在 open 时冻结当文件被外部修改后fingerprint 发生变化旧缓存自然不命中从而满足 close-to-open 一致性。这也带来一个取舍托管模式基于 Slice ID 实现更细粒度的缓存隔离而外部模式依赖文件 fingerprint粒度更偏文件级缓存失效范围可能更大。但对于已有数据可能被外部系统修改的场景这是保证一致性所必须接受的代价也是后续可以继续优化的方向。除了基础读缓存系统还支持缓存预热、防击穿、TTL 驱逐和透明降级。例如可以通过 warmup 命令提前预热热点数据分布式缓存可以按目录前缀批量预热当缓存层不可用时系统也可以自动降级为直接读取底层存储避免缓存故障影响业务读取。05 多租户与弹性扩展在云厂商场景下统一存储层需要同时服务多个业务、多个租户和多个文件系统。因此我们将元数据服务设计为无状态架构客户端通过 ZooKeeper 完成服务发现和负载均衡元数据服务节点可以按需水平扩展从而提升整体访问能力和可用性。多卷隔离则依赖 FoundationDB 的 Key 前缀设计。每个文件系统使用独立的fsname前缀不同卷之间拥有独立的 Key 空间使一个 FoundationDB 集群可以同时承载多个文件系统。新增文件系统时也不需要重启元数据服务可以在线完成扩展。在多节点部署下还需要同步配额、权限、目录保护、任务状态等运行时信息。我们通过 ZooKeeper 实现跨节点变更通知并结合防抖合并、按 Key 精准刷新和定时轮询兜底机制保证配置变更能够及时同步到各个元数据服务节点。通过无状态元数据服务、fsname前缀隔离和 ZooKeeper 状态同步系统可以在保持多租户隔离的同时实现服务层和元数据层的横向扩展。06 百亿级元数据验证我们基于 JuiceFS 1.3.0 和 FoundationDB 7.3 进行了百亿级元数据测试。测试环境采用 6 台 x86 服务器操作系统为 Kylin V10 SP3FoundationDB 采用 triple 三副本和 SSD 存储引擎部署。这组测试在已经写入 108 亿条元数据的基础上进行压测。结果显示在百亿级数据规模下FoundationDB 的单操作延迟与基准数据基本持平部分操作如readdir_1k、lookup甚至表现更好。整体来看单卷元数据规模达到 108 亿后元数据操作延迟仍可以保持在亚毫秒到 2ms 级别说明大规模数据量下没有出现明显性能衰减。在极限写入测试中我们通过 15 个并发进程执行juicefs clone克隆元数据验证 FoundationDB 的写入上限。测试结果显示在 6 台机器 SSD 配置下稳定阶段写入吞吐约为11,00015,000 inode/s。从瓶颈分析来看主要压力集中在 Storage 写入队列和磁盘 I/O而不是 CPU 或网络。后续可以通过增加 Storage 进程、提升磁盘性能或扩展 Commit Proxy、TLog 等组件进一步提升读写能力。高可用方面我们分别验证了 1 台和 2 台机器故障场景。在 1 台机器故障时服务保持可用FoundationDB 会自动触发副本修复和数据迁移在 2 台机器故障时服务仍然可用但集群容错能力会降为 0不能再容忍更多故障。故障恢复后系统会触发数据重新均衡测试中完整恢复时间约为 4 小时。这个过程会带来额外 I/O 压力因此生产环境需要重点关注磁盘水位、单盘故障和恢复期资源消耗。容量规划方面测试数据显示50 亿 inode 时 FoundationDB 磁盘占用约 6.1TB108 亿 inode 时约 10.1TB。综合三副本、压缩效果和预留空间后可以按约 120GB / 亿 inode作为基础容量估算。通过这组验证我们基本确认FoundationDB 可以支撑单卷百亿级元数据规模并在已有百亿级数据的情况下保持稳定的元数据访问性能。同时三副本架构具备较好的故障恢复能力但生产环境仍需要做好容量规划、磁盘监控和恢复期 I/O 管理。07 小结与未来规划目前这套基于 JuiceFS FoundationDB 的统一存储接入层已经在大数据存算分离场景中完成了核心能力建设包括统一客户端接入、外部数据利旧、多级缓存加速、百亿级元数据管理以及多租户扩展能力。后续我们会继续围绕湖仓一体、AI 训练和存储治理等方向演进。在湖仓一体方向上我们计划基于统一存储层加强与 Iceberg、Hudi 等表格式的集成让上层数据湖和数据仓库场景能够复用统一的存储接入、权限管理和缓存加速能力。AI 训练方面后续会进一步优化缓存预热和就近缓存能力降低训练任务中的远端读放大和 GPU 等待时间。同时也会结合快照能力探索模型 checkpoint 管理让训练过程中的中间状态保存、恢复和复用更加高效。在存储治理方向上我们还会探索智能分层能力根据数据访问频率在 SSD、HDD 和对象存储之间自动迁移从而在性能和成本之间取得更好的平衡。对于更大规模的云上部署场景也会继续推进跨集群联邦能力实现多集群之间的元数据同步、路由和统一访问。未来我们会继续围绕性能、成本、弹性和数据治理能力迭代让更多业务能够以统一方式访问和管理底层数据。