跳到内容

第 7 卷 / 第 4 章 / 第 3 课

4.3 从 HDFS 到 Spanner:工作负载决定架构 ​

HDFS 与 Spanner 都跨机器保存数据,但服务目标不同:前者面向大文件和高吞吐顺序访问,后者面向全球分片、同步复制,并在默认的可串行化隔离下提供外部一致事务。不能用产品规模替代工作负载分析。

HDFS 分离元数据与数据路径 ​

NameNode 维护命名空间、文件到 block 的映射和副本状态;DataNode 保存实际 block。客户端先查询元数据,再直接与 DataNode 传输数据。下图表示使用副本的文件写入管线;读通常选择一个合适副本,出错后重试其他副本,不会把每次读都沿整条管线传一遍。

text
Client ──metadata──> NameNode
  │
  └──block stream──> DataNode A → DataNode B → DataNode C

大 block 减少元数据数量和寻址开销,流水线复制提高写入吞吐。机架感知副本放置在网络成本与故障域之间权衡。

HDFS 适合大文件、批处理和顺序流式读写。单个文件通常只有一个写者,可追加而非随意原地修改;小文件过多又会消耗 NameNode 的文件和 block 元数据内存。它不适合低延迟随机更新,也不提供完整通用 POSIX 语义。纠删码文件的数据布局与这里的副本管线不同。具体 block 大小和副本数由部署配置决定,不应把某个默认值写成协议定律。

元数据高可用仍需要协调 ​

Active/Standby NameNode 需要共享编辑日志或一致的日志机制、故障检测与 fencing。以 Quorum Journal Manager 为例,Active 把编辑记录写入 JournalNode 多数派;Standby 追赶这些记录后才能安全接管。配置自动故障转移时,ZKFC 通过 ZooKeeper 协调选主。检测到 Active 不健康还不够,fencing 必须阻止旧实例继续提供不安全的服务,不能让“我还活着”成为两个 Active 的共同意见。

DataNode 定期上报 block 状态,NameNode 对缺副本执行补复制,对过量副本安排删除,并考虑故障域放置。恢复流量要限速,避免节点故障触发的复制风暴影响前台作业。

Spanner 把分片、副本与时间协议组合 ​

Spanner 将数据按 key range 分片,复制组通过共识确认写入;各副本不必在每个瞬间完全追平。事务层协调跨分片读写,TrueTime 暴露物理时间的不确定区间,与 MVCC 等机制共同支持外部一致性和历史时间读取。

关键点不是“有 GPS/原子钟所以数据库很快”,而是:

  • 复制组用共识决定写入顺序;
  • 事务需要并发控制和跨分片协调;
  • 时间 API 把误差作为区间暴露;
  • 协议通过等待等方式使提交时间戳尊重真实时间顺序。

例如提交时间戳选为 s,commit wait 要等到 TrueTime 能确认真实时间已超过 s,再让事务对外完成。单纯把机器时钟调准,不能替代这个顺序保证;跨分片事务还要处理多个参与组的原子提交。

这些保证要支付相应的网络、共识和提交等待成本。schema 与 key 设计仍要避免热点范围。

选择存储先写访问模式 ​

需求倾向
PB 级大文件顺序扫描、批作业分布式文件/对象存储
高写吞吐、按分区键访问、可调一致Leaderless 宽列/键值系统
全球事务、关系查询、外部一致分布式 SQL,接受协调成本
小规模强一致元数据共识 KV,不存大对象

还要明确:对象大小、请求率、范围查询、事务范围、读新鲜度、地域、RPO/RTO、成本和运维能力。

备份与副本不同 ​

副本会同步应用误删除、错误写入和应用 bug。备份需要独立故障域、保留周期、不可变性和恢复演练。

对任何存储系统都要证明:

  • 能恢复到哪个时间点;
  • 恢复多久;
  • 加密密钥和 schema 是否一起可恢复;
  • 恢复环境如何避免覆盖生产;
  • 最近一次完整演练是什么时候。

参考资料 ​

Built with VitePress | Software Systems Atlas