聊分布式文件系统设计之前,先说我上周的一次评审经历。有个团队准备把几千万个小文件全部塞进单机文件系统,理由是“数据量也不大”。我当时反问了一句:如果半年后数据翻十倍,你的目录树还能扛住吗?这个问题,恰恰是分布式文件系统设计要解决的核心问题:不是把硬盘变多,而是让一堆普通机器像一个文件系统那样工作,同时还能扛住容量增长、并发访问和单点故障。
很多人一听到“分布式文件系统”,第一反应是HDFS、Ceph这类开源项目,然后就开始纠结到底选哪个。但作为做系统设计的人,我更建议先搞清楚背后的设计逻辑:数据怎么分、元数据怎么管、一致性怎么保证、故障怎么恢复。这些底层逻辑搞明白了,选型、自研、甚至调优,心里都有谱。这篇内容适合正在做存储选型、准备自研文件系统、或者做架构设计评审的工程师,我尽量把设计主线和实操要点讲透。
1. 先想清楚要解决什么问题
1.1 三个绕不开的原始需求
任何分布式文件系统的诞生,都是被逼出来的。回顾一下你遇到的实际场景,大概率逃不出这三个问题:容量不够、吞吐不够、扛不住单点故障。
先说容量。单机文件系统哪怕做了RAID,扩到几十TB甚至上百TB,成本先不说,单块盘的重建时间已经让人崩溃。分布式文件系统的第一个价值,就是可以把几十台、几百台机器的存储空间拼成一个逻辑空间,需要扩容就加机器,不需要停机迁移数据。
再说吞吐。单机的网络带宽、磁盘IOPS是有上限的。如果业务需要几十GB/s的读带宽,或者几十万次元数据操作每秒,单机基本不可能做到。把请求分散到多台机器并行处理,是分布式文件系统在性能上的核心优势。
最后是可用性。硬盘会坏、机器会宕、机房会断网,这是常态。单机系统一坏全完蛋,分布式系统通过多副本、自动恢复,让某台机器挂了之后,客户端还能正常读写。这段时间系统没感知,数据不丢,这才叫高可用。
这三个需求听起来很直白,但真正做设计的时候,它们之间是互相打架的。要吞吐就要多副本并行,多副本就要占额外空间,占空间就挤压了有效容量。要强一致就要多节点同步,同步就增加写延迟。所以设计的第一步,不是找一堆开源组件拼起来,而是先明确:你的系统到底优先保什么。
1.2 CAP 到底怎么选
任何分布式系统设计都绕不开CAP理论:一致性、可用性、分区容错性三者不可兼得。放在文件系统这个场景里,“分区容错”是默认必须选的,因为网络断连、机器宕机是常态。真正要权衡的,是在网络分区发生时,你是选择继续服务但可能读到旧数据,还是宁愿暂时拒绝服务来保证数据一致。
传统的文件系统语义是非常强一致的,比如POSIX里,你写完了文件再打开,一定能看到刚写的内容。但在分布式环境下,要做到每个副本都同步完成才返回成功,写延迟会非常高。HDFS的经典做法是写所有副本成功才算成功,换来的是强一致;但代价是写性能受最慢副本影响,跨机房的场景尤其明显。
在自研或者二次开发时,我通常给团队的建议是:元数据操作(比如创建文件、重命名、删除目录)必须强一致,这些操作串行化处理,走共识协议;数据内容的写入可以用强一致加租约机制控制,或者根据业务需求选择写多个副本才返回,这样不会出现“写成功后读不到”的诡异情况。数据块可以用最终一致性模型,靠后台校验和修复逐步收敛。
这个取舍会在第4节详细展开。这里先记住一个关键原则:一致性级别不是一个全局开关,而是可以按操作类型精细控制的。好的文件系统设计,会把“元数据强一致”和“数据最终一致”在一个系统里共存,既保证语义可靠,又给性能留余地。
1.3 用可量化指标驱动设计
做设计最忌讳“感觉差不多”。最好的方式是一开始就定一组可量化的指标,之后所有架构决策都围绕指标展开。我一般会列这样一组需求指标作为设计输入:
| 指标 | 示例值 | 设计影响 |
|---|---|---|
| 总容量 | 5PB | 决定集群规模、副本策略 |
| 单文件最大大小 | 1TB | 决定分块大小和元数据量 |
| 文件数量 | 10亿 | 决定元数据节点架构 |
| 读带宽 | 20GB/s | 决定数据节点数量、网络架构 |
| 写带宽 | 5GB/s | 决定写入链路、刷盘策略 |
| 元数据操作QPS | 5万/s | 决定元数据分片策略 |
| 可用性 | 99.99% | 决定副本数、故障恢复速度 |
这些数字看着简单,但每一项都会直接影响存储引擎、网络协议、缓存策略的选型。比如“文件数量10亿”这一个条件,就基本决定了元数据节点不可能只用一台机器内存硬扛,必须做元数据分片或者用KV存储来做目录树。再比如“写带宽5GB/s”,如果单机磁盘写吞吐是200MB/s,那至少需要25台数据节点同时写入,这直接决定了副本放置和调度策略。
我见过很多设计文档,一上来就画架构图,画到一半发现支撑不了需求指标,又回去改方案。正确的顺序是先定指标,再定架构,最后才是选型。这个顺序换来的时间,比在后期返工省得多。
2. 整体架构:先分角色,再谈细节
2.1 元数据节点:文件系统的“大脑”
分布式文件系统区别于分布式对象存储和分布式KV的一个关键点,是需要维护目录树结构。文件系统里有“路径”的概念,有目录层级,有权限,有软硬链接。这些信息在分布式系统里必须有一个集中的“大脑”来管理,这就是元数据节点,也叫控制节点、NameNode、MDS。
元数据节点主要存三类信息:第一个是目录树结构,即这个路径下面有哪些子目录和文件;第二个是文件属性,包括文件大小、创建时间、权限;第三个是数据块映射关系,也就是这个文件被切成了多少个块,每个块放在哪几台数据节点上。
需要特别提醒的是,元数据节点的数据量虽然比真实数据小很多,但架不住文件数量大。每10亿个文件,按每个文件管理1KB元数据来算,就是1TB内存左右,这可不是一般机器能扛住的。所以大型文件系统的元数据节点本身就是一个复杂的分布式系统,需要做分片、做集群化。HDFS的NameNode之所以在文件数过亿后会出现Full GC问题,本质上就是单机内存装不下这么多对象了。
在设计元数据服务时,我的经验是:把它拆成“命名空间层”和“块映射层”。命名空间层管目录和文件名,块映射层管文件和块的对应关系。这两层的访问模式不一样,命名空间层以随机小事务为主,块映射层可以设计成批量查询。拆开之后,两层可以分别做缓存、分别做分片,性能调起来也更有针对性。
2.2 数据节点:真正的存储单元
数据节点是文件系统里真正存数据的角色,一般也叫DataNode、ChunkServer、Storage Node。每一台数据节点管理本地的若干块存储,对外提供块的读写、校验、租约上报、数据块扫描修复等服务。
数据节点的部署密度对整个系统成本影响很大。业界在数据密集型的场景下,通常把每台物理机的存储容量配到4TB到16TB不等,同时配2到4块NVMe SSD做读写缓存,这样既能利用大容量机械盘的性价比,又能通过SSD缓解随机小IO的性能瓶颈。这个配置我在多个项目里验证过,性价比很稳。
数据节点和元数据节点之间的交互包括:启动时注册上报本机存储信息;周期性发送心跳和块报告;执行元数据节点下发的块删除、复制、迁移指令。设计数据节点时有个容易忽视的点:数据节点不能完全被动执行指令,它必须有主动体检的能力。比如定期扫描本机所有块做校验和,发现磁盘坏道、校验和错误时主动上报。主动体检和被动执行之间的节奏要设计好,否则数据节点在高负载时还在做SCSI检查,业务IO会被大大拖慢。
数据节点不关心文件名,只关心“块ID”。这个抽象非常重要,它让数据节点的实现变得很干净,不用关心文件语义,只管好自己硬盘上那一堆编号的数据块。
2.3 客户端:协议转换的第一站
客户端是整个文件系统对外的门面。对上层应用来说,它就是一个可以open/read/write的“盘”或者“挂载点”。对底层架构来说,它需要负责把用户的路径请求解析成元数据查询,把文件读写转换成对数据节点的块读写。
在接口设计上,业界有三种常见模式。第一种是POSIX兼容接口,通过FUSE或者内核模块挂载,应用无感,但要处理锁语义、缓存一致性,复杂度最高。第二种是对象存储接口,比如S3风格,简单易用,但对强一致语义的支持需要额外处理。第三种是自定义API,灵活性最大,但生态需要自己建设。
我见过一些团队一上来就追求POSIX兼容,结果在分布式文件系统上实现全语义POSIX,比如字节范围锁定、垃圾回收、mmap,工作量成倍上涨,最后项目烂尾。这里我的建议非常明确:如果你的应用能改代码,优先用自定义API或对象接口;只有HPC、传统BI这类必须有POSIX语义的场景,才值得投成本去兼容。这是被反复验证过的现实选择。
2.4 为什么读写路径要走“直连”而非“透传”
在设计客户端访问数据的路径时,最容易踩的坑是把所有读写请求都经过元数据节点转发。这个设计实现起来简单,但很快会撞上性能瓶颈:元数据节点的带宽、CPU、连接数全都成了系统的天花板,而且数据流和元数据流相互干扰,一个大的读请求就能把整个命名空间服务拖垮。
正确的设计必须是“控制流和数据流分离”。客户端先从元数据节点拿到数据块的分布信息,比如某个块在数据节点A的、B的副本上,然后客户端直接与数据节点A、B建立连接去读写数据。元数据节点只处理定位和授权,不碰实际数据。这就是HDFS、GFS等系统广泛采用的方式。
实际落地时,这个直连模式还需要配套两个机制:一个是租约或授权票据,避免客户端拿一次映射关系后永久有效,万一文件被删除或块被迁移,客户端还能通过过期失效来触发重新查询;另一个是重试机制,客户端直连数据节点失败后,不要立刻报错,而是重新向元数据节点获取新的块位置,换一台数据节点重试。把这两个机制做扎实,直连模式才能真正稳定。
3. 数据怎么放:分片、定位与副本
3.1 块大小:细节里的取舍
文件不可能作为一个整体存在一台机器上,必须切成块分布到多台机器。块大小这个参数看起来是个配置项,但实际影响很深。
设置太大,比如512MB一个块,对于小文件来说,一个文件才几KB,也要占一个块的位置,元数据效率极低。设置太小,比如1MB一块,一个1GB的文件就要拆成1024个块,元数据节点要管理1024条映射记录,内存和网络开销直线上升;而且块多了以后,单个文件的读取需要并发连接多台数据节点,调度开销也很大。
经典的选值是64MB到128MB。这个数值的合理性在于,它是在“元数据开销”和“IO效率”之间折中出来的。一个128MB的块,连续读写可以在几秒内完成,足够摊薄网络握手和寻道开销;同时,一个10PB的集群,如果每块128MB,元数据量级也就千万到亿级别,仍然在可控范围内。
具体取值还要看业务场景。如果你主要存小文件,比如图片、日志碎片,块大小可以调小到8MB或者16MB;如果主要存超大文件的训练数据集,块大小可以放大到256MB甚至1GB。实操中我一般这样定:先统计业务文件大小的中位数和P99值,然后让块大小至少是P99文件大小的4到8倍,这样大部分文件一个块就能搞定,元数据操作最少。
3.2 数据定位:三种主流思路对比
切完块之后,紧接着的问题就是:客户端要找某个文件的第N个块,系统怎么知道它放在哪?这是分布式文件系统的核心路由问题。业界有三类主流方案,各有各的使用场景,我直接说对比。
集中式元数据表的思路是:所有文件到块的映射关系都存到元数据节点上,客户端每次读取之前先查一次元数据。优点是实现简单,缺点是元数据节点容易成为瓶颈。HDFS走的就是这条路,它能支撑数百万文件的规模,但再往上就要做联邦或分片。
一致性哈希的思路是:不引入中心路由,通过哈希函数直接计算出某个块ID对应在哪些机器上。优点是定位速度快,不需要查询;缺点是增加和删除机器时,数据迁移量很大,而且哈希无法感知机架拓扑和磁盘容量差异。
CRUSH算法的思路是把“块ID”和集群拓扑、权重信息作为输入,通过确定性伪随机计算得出副本位置。它唯一的决定性输入是集群地图,不依赖中心路由查询,新增节点时数据迁移量只和权重相关,可控得多。Ceph的PG和OSD映射就是CRUSH的典型实现。代价是算法复杂度高,故障域调整后需要重算,对实现质量要求很高。
| 定位方案 | 优点 | 缺点 | 典型系统 |
|---|---|---|---|
| 集中式元数据表 | 实现简单、灵活 | 内存和性能瓶颈 | HDFS |
| 一致性哈希 | 定位快、去中心化 | 迁移量大、网络拓扑感知差 | 部分自研系统 |
| CRUSH | 分布式计算、拓扑感知 | 实现复杂 | Ceph |
给个直接的选型经验:中小规模自研,团队5人以内,优先集中式元数据表,快速跑通业务;规模化到了数据节点上百台,再考虑迁移到CRUSH这类算法。量变引起质变,这个临界点通常在千节点左右,过早投入高度复杂算法,研发成本划不来。
3.3 副本放置:三副本放法有讲究
数据安全靠什么?靠副本。业界最常见的配置是三副本,即在集群内保存三份同样的数据,这样即使两台机器同时宕机,数据也不会丢。但副本放哪,是很有讲究的。
最能说明问题的是“机架感知”策略。比如你有一个三副本,如果三个副本都放在同一台机架上,这台机架的交换机挂了,数据全部不可访问。所以合理的放置策略是:第一个副本随机选择一台机器;第二个副本放在同机架但不同机器上,保证机架内网络传播快,写入性能好;第三个副本放在不同机架甚至不同机房,保证抗住整机架断电的极端情况。
这里有个关键数字:机架间网络带宽通常只有机架内带宽的十分之一甚至更低。副本策略如果把三个副本全部跨机架,写路径会非常慢;如果全部集中在机架内,又扛不住机架级故障。所以“两个副本同机架、一个副本跨机架”在大多数情况下是性价比最高的配置,兼顾了写入延迟和容灾能力。
副本数量也不是越少越好。为了追求成本把副本降到2,数据丢失概率会显著上升,因为集群中第二台机器故障导致副本降级到1的时间窗口变长。实操中,如果业务对成本极度敏感,我建议也不要低于2副本,必须再加“定期快照”或者“离线备份”兜底,否则硬盘损坏可能直接造成不可恢复的数据丢失。
4. 一致性、租约与容错设计
4.1 一次写入请求是怎么走完的
说清楚文件系统的一致性,最好以一次写入请求为例。假设客户端要写文件F的第1024号块,设计了三个副本,分别位于数据节点A、B、C上,其中A是主副本。整个写入流程可以拆成几个阶段。
第一步,客户端向元数据节点发起写请求,请求带上文件路径、块ID、数据长度等信息。元数据节点校验权限后,返回当前块的主副本位置和租约信息。这里的租约相当于一个临时授权,告诉客户端“在某个时间段内,你可以把这个块的主副本视为有效”。
第二步,客户端将数据流式发送给主副本A。A写成功后,把数据同时转发给B和C。这里要注意的是,转发是链式的,A到B再到C,形成一个pipeline,这样数据不会同时给三台机器造成瞬时冲击。等到B和C各自确认写完,A统一回报客户端“写成功”。
第三步,客户端在收到A的成功回报后,再向元数据节点提交这个块的备份完成信息。元数据节点更新文件大小和块时间戳,整个写入流程结束。
从用户角度,这种流程的感知是“写操作比单机文件系统慢”,因为要等三份都写完。但换来的是任意一台数据节点挂了,另外两个副本还能保证数据可读、可恢复。
4.2 租约机制:锁的分布式替代品
传统的单机文件系统用文件锁来保证并发访问的一致性。分布式系统里,锁如果处理不好会变成性能灾难和死锁温床。租约就是分布式领域替代锁的一套成熟思路。
租约的本质是带时间的授权。元数据节点给客户端一个租约,里面包含授权生效时间,比如30秒。客户端在租约有效期内可以反复写同一个文件块,不用每次写都去元数据节点申请。租约到期了,如果客户端还在写,必须重新申请;如果客户端宕机,元数据节点只需等待租约过期就能安全地把该块的写权限分配给其他客户端。
租约时间长短的设计很有讲究。时间太短,客户端频繁申请租约,元数据节点压力大;时间太长,如果客户端宕机,其他客户端要等很久才能接管写权限,系统恢复慢。我实际项目中一般是30到60秒,同时允许客户端在心跳里自动续约,这样可以兼顾性能和故障恢复速度。
还有一点,租约必须按“块”粒度管理,而不是按“文件”粒度。因为同一个文件的不同块可能在不同数据节点上,如果按文件粒度管理租约,粒度太粗,锁竞争会很严重。粒度细化到块之后,并发度提高到块级别,写性能才有保证。
4.3 元数据一致性:共识协议的应用场景
数据块的一致性可以靠租约和副本确认来保证,但元数据的一致性必须靠更强的机制,因为它决定的是整个系统的逻辑正确性。比如两个客户端同时创建同名文件,系统必须保证只有一个成功;再比如一个文件正在被写入时,另一个客户端发起删除,系统必须给出一个明确时序。
这个问题的标准解法是用共识算法,最常见的是Raft和Paxos。元数据节点的所有状态变更——创建文件、分配块、记录块副本位置——都作为一条日志记录提交到共识组,超过半数节点确认之后,才真正生效。这样即使某个元数据节点实例宕机,其他实例也能接着服务,且不会出现两个实例各自为政的状态分叉。
但共识算法是有性能代价的。一次日志提交通常要经历两次网络往返,再加上磁盘刷盘,在跨机房的场景下,元数据操作的QPS会被压到几千级别。如果你第1节设计了5万QPS的元数据操作指标,单组Raft肯定撑不住,必须对元数据做分片,比如按目录哈希分成多个分片,每个分片独立跑一组Raft。
这里我补充一个实际踩过的坑:不要为了追求极致性能跳过元数据日志落盘。很多人在测试环境为了速度,关闭了Raft日志的fsync,结果一压实测就出现元数据丢失,文件系统直接报废。共识算法里的每一条安全性质都是有大前提的,日志落盘这个动作绝对不能省。
4.4 故障检测与数据自愈
系统设计得再好,故障仍然是常态。分布式文件系统能不能真正高可用,就看两件事:故障发现快不快、数据修复快不快。
故障发现依赖心跳。数据节点每隔几秒向元数据节点发一个心跳包,心跳包里带上本机的存储压力、IO延迟、块数量等健康状况。如果元数据节点连续几个心跳周期没有收到某台数据节点的消息,就判定该节点故障,开始调度它的副本去补建新副本。
数据自愈是这个环节的核心。假设文件F有3个副本,其中一份在宕机的机器上,那么系统需要找一台新的数据节点,从其他两个健康副本之一拉取数据,重新生成第三份副本。这个过程要注意一个顺序问题:不要等故障确认了才去复制,可以在节点“疑似故障”时就启动数据扫描和复制预演,这样能大幅缩短恢复窗口。
还有一个容易忽视的点:数据自愈的带宽不能抢占正常业务IO。我一般建议对自愈复制流量设置配额,比如单机最多使用30%的带宽做复制任务,超过配额就排队。否则某台机器刚故障,整个集群都被复制流量打满,正常读写全部超时,这是典型的“救火反而引发新火灾”。
5. 落地时踩过的坑与排查实录
5.1 小文件杀手:目录和文件数一多,整套系统都在哭
分布式文件系统最怕的不是大文件,而是海量小文件。我有一个项目,数据不大,总共不到1TB,但文件数量到了3亿个,系统直接卡死。为什么?
问题在主元数据节点。每个文件需要一条元数据记录,就算每条记录只有1KB,3亿个文件就要300GB内存。同时,创建小文件的过程需要元数据节点分配块ID、建立映射、记录更新时间,每一步都是一次日志提交,海量小文件的元数据操作把共识组压得喘不过气来。
实操中的解法有几种。首先是业务侧合并,把大量小文件合并成大文件,比如日志文件按小时合并成SequenceFile,或者用HAR归档;其次是调整块大小,把小文件专用的区域块改小;最后是预创建机制,批量预分配块ID,减少每次创建的日志交互次数。三者组合使用,我遇到过的场景能把元数据QPS压力下降80%以上。
业务侧合并优先级最高,因为根治了元数据量的膨胀。如果你的业务有“一个系统天生就是几亿个小文件”的场景,我建议在系统设计阶段就预留“文件聚合”这个接口,让写入端先聚合成大块再落盘,不要等到线上卡死才想对策。
5.2 数据倾斜与热点:哈希救不了所有场景
理论上,块分布是均匀的,但实际运行一段时间后总会出现热点。比如某个目录下的文件被大量并发读取,这部分块所在的数据节点IO被打满,其他节点却在空闲。
解决数据倾斜,第一步是监控,你需要知道哪些数据节点负载高、哪些块被频繁访问。第二步是迁移,把热点块挪到负载低的机器上。这要求系统支持块的动态迁移,并且迁移过程对客户端透明,客户端重试一次就能从新的数据节点读取。
第三步是预分片。如果你在设计阶段就知道某些场景会高频访问特定数据,可以在写入时把相关数据打散到更多数据节点上。比如用内容哈希而不是顺序ID分文件,这样同一个目录下的文件也会均匀分布。哈希不是万能的,但它可以在源头避免很多“隐热点”。
这里要警惕一个陷阱:不要把“迁移”做成全量迁移。有团队为了均衡,定期把所有块全局重排,结果均衡的代价是数据流量比业务IO还大,等于花了300%的网络带宽去过度均衡。正确做法是只对超过阈值的热点块或者超大数据块做定点迁移。
5.3 长尾延迟与慢节点
分布式系统的性能,往往不是由最快节点决定的,而是由最慢节点决定的。写三副本的时候,如果其中一个副本落在慢磁盘上,整个写入可能被拖慢到三倍时间。这就是长尾效应。
处理方案通常有三层。第一层是客户端并发控制,写多个副本时允许“部分副本成功”,只要达到可配置的最低副本数就返回成功,后台继续补齐剩余副本。第二层是数据节点侧慢盘检测,连续几个周期IO延迟超标就向元数据节点上报,元数据节点把新块调度到健康节点。第三层是客户端超时重试,不要因为一次慢IO就判定故障,设置合理的重试次数和退避时间。
还有一个我很想强调的点:不要盲目增加副本数来对抗长尾。三副本都慢,再增加到五副本,只会让整个写入链路更长、被拖慢的概率更大。正确做法是提升单个副本的稳定性,比如给数据节点配NVMe缓存盘、优化刷盘策略,而不是靠堆积副本解决。
5.4 双写与脑裂的唯一出路:fencing机制
网络分区最让人头疼的后果,是同一个文件块出现了两个“主副本”同时接受写入,两边的数据产生分叉,正式的术语叫脑裂。脑裂一旦发生,轻则数据不一致,重则文件系统整体损坏无法恢复。
防止脑裂的防御机制叫fencing,中文直译就是“隔离围栏”。核心思路是:元数据节点给客户端发租约的时候,同时给数据节点发一条“上一任主副本失效”的信号。新主副本身份确认之前,必须先让数据节点拒绝旧主副本的写入请求,保证同一时间只有一个主副本能写入。
实际操作中,fencing通常结合存储层的原子CAS操作:数据节点维护一个“当前写租约持有者”标识,写入时校验标识是否匹配,不匹配直接拒绝。每一步都落实到代码里,不要依赖“网络分区之后元数据节点认为谁应该活下来”这种假设。分布式系统的原则是:宁可拒绝请求,也不要在不确定状态里冒险写数据。
6. 从设计到落地:时间与人力投入建议
最后聊点实际的。如果你现在接手一个任务,要用3到6个月时间做一个能支撑PB级存储的分布式文件系统MVP,我的建议是分三个阶段推进。
第一阶段,先用集中式元数据表加简单数据节点路由快速实现一个可用闭环,支持文件的创建、删除、读取、写入,以及三副本基础写入,这是跑通主链路。第二阶段,加上租约机制、心跳检测、块自愈,让系统具备基本的故障恢复能力。第三阶段,再做元数据分片、数据均衡、热点迁移等优化项,把这些非核心但拉高上限的能力补上。
团队规模上,一个5人左右的小团队足够完成前两个阶段,前提是每个人都要有全栈能力,因为分布式文件系统的每一层都可能是瓶颈。真正困难的是第三阶段的性能优化,这个阶段需要专门的存储引擎工程师、网络工程师和测试同学一起上。
人力上我特别想提醒一点:分布式文件系统的测试成本被严重低估。你需要在测试环境模拟交换机故障、磁盘损坏、数据节点断网、租约到期等异常场景,每一个场景都要有对应的测试用例和恢复验证。不做故障注入测试的分布式存储系统,本质上是没有高可用能力的。
我个人在实际项目里的体会是:分布式文件系统设计,方法论占一半,另一半是在各种故障现场被毒打出来的经验。上面这些落地方案和建议,很多都是我用真金白银的线上事故换来的,希望能帮你在设计阶段就避开这些坑。如果你正在做存储方向的架构设计,建议把这篇文章里的几个关键决策点——一致性模型、块大小、副本放置、租约策略——都写成设计文档里的硬性章节,评审的时候一条条过,比画一堆漂亮架构图管用得多。