架构 (IT)系统架构师

为全球分布的对象存储系统设计一个容错、强一致性的元数据控制平面,该系统能够索引数十亿个对象,跨多个异构存储层,处理乐观并发控制下的并发命名空间修改,并保证在热点路径上具有亚毫秒的读取延迟?

用 Hintsage AI 助手通过面试

问题的回答

对象存储的演变已从早期的 CephSwift 实现的集中式元数据数据库,转向能够进行超大规模的分布式架构。这一转变在需要 POSIX 风格语义(原子重命名、严格可序列化)与管理数十亿个键所需的水平可扩展性之间引入了根本性的紧张关系,这些键分布在 SSDHDDTape 层中。核心问题在于协调分布式节点之间的并发变更,而不受到传统 两阶段提交 (2PC) 协议或基于 Paxos 的全局共识的延迟惩罚。

解决方案需要一个 分片共识架构,每个分片负责使用 Raft 协议确保该边界内的线性一致性。一个 元数据路由器 层根据目录前缀引导客户端请求,利用 一致性哈希 来维护范围查询的局部性,同时实现水平扩展。为了性能,热点元数据保存在一个 分层缓存 中,包括用于 L1 的 Redis 和用于 L2 持久化的本地 RocksDB,而冷元数据则压缩为 Apache Parquet 文件存储在 S3 上,以降低存储成本而不牺牲耐久性。

生活中的情况

一家媒体公司从 AWS S3 迁移到私有混合云,需要管理 20 亿个视频片段,并跟踪编码配置文件、DRM 密钥和生命周期状态。他们的初始架构使用 MongoDB 进行自动分片,但在块迁移期间出现不可预测的延迟峰值(100-500ms),且缺乏跨分片原子事务,导致在并发文件夹移动过程中数据损坏。

解决方案 1: CockroachDB (分布式 SQL)

这种方法提供了原生的水平扩展和可序列化隔离,采用 Google Spanner 风格架构。主要优势是熟悉的 SQL 接口,可用于对元数据进行复杂分析查询。然而,由于多区域共识复制,该系统表现出较高的写入放大(3-5 倍),且在病毒内容上传高峰期间,延迟持续超过 20ms。对于 PB 级别的元数据存储,许可成本对组织来说被证明是经济上不可行的。

解决方案 2: Apache Cassandra 与轻量级事务 (LWT)

Cassandra 提供了巨大的写入吞吐量和可调的一致性,基于 Paxos 的 LWT 提供了可线性化的操作。这项技术在处理高速元数据流时表现出色,无单点故障。然而,Paxos 的平均延迟为 15ms,并在并发访问下显著下降,而二次索引“按上传日期列出”查询需要昂贵的全表扫描,使其不适合交互式用户体验。

解决方案 3: 带 Raft 的自定义每目录分片

该设计将每个用户目录映射到一个专用的 Raft 共识组,确保频道内的操作(主要访问单元)是线性化和快速的,因为可以进行本地磁盘访问。该架构支持通过分片局部事务进行原子重命名,而无需跨网络协调。虽然这为热门目录(热点)引入了复杂的重新分片逻辑,并且需要一个复杂的客户端路由库,但它与视频内容自然按创作者划分的工作负载模式完美匹配。

结果: 在病毒活动期间,系统成功保持每秒 80,000 次元数据操作,P99 延迟低于 3ms。自动化分层策略将 90% 的老化内容转移到冷存储,基础设施总成本降低了 60%,同时对活动内容保持严格的一致性保证。

候选人常常忽视的内容

当一个热门对象过期或被更新时,您如何防止元数据缓存的洪水效应?

候选人通常建议采用简单的 TTL 基于过期的方案,而不考虑惊群保护。正确的方法是实现 基于租约的缓存,其中缓存条目携带短效租约令牌,确保只有租约持有者从后端刷新,而其他人则等待或短暂提供过期数据。将此与 概率性提前过期(为 TTL 添加随机抖动)和 singleflight 模式(如在 Go 的 singleflight 包中实现)结合使用,旨在将并发相同请求合并为一个后端查询,从而在缓存未命中的情况下防止数据库过载。

在实时分片拆分(重新分片)操作期间,确保元数据一致性的策略是什么?

许多人建议在迁移期间停止写入,这违反了可用性要求。正确的技术使用 影子索引双写 协议。首先,将新目标分片实例化为源分片的延迟副本,使用 Raft 日志传输。一旦同步,切换写入路径到新分片,同时在旧分片中维护一个 墓碑 日志,以处理延迟读取。像 etcd 这样的 协调服务 以原子方式更新路由表,而 MVCC 时间戳确保在过渡期间读取一致的快照,拒绝跨越拆分边界的请求,直到原子切换完成。

当异步垃圾收集或分层迁移静默失败时,您如何调和元数据索引与物理存储层?

这需要一个 事件源 的方法和用于分布式事务的 Saga 模式。元数据服务发出 领域事件 (例如,“TieringInitiated”)到 Apache Kafka 日志,存储消费者通过幂等回调确认成功处理。如果存储层未能在指定超时时间内迁移对象,元数据服务将接收一个 Saga 超时事件 并触发一项补偿事务,将元数据状态恢复到 “HOT”。此外,实现一个后台 调节扫描器,使用 Merkle 树 高效识别元数据与物理存储 HEAD 请求之间的差异,在无需全表扫描的情况下修复不一致性。