
未经同意请勿转载副标题Slab、Column、Region、Fault Domain——微软真正的存储语义适用版本Azure Local 2506 / 2510 / Windows Server 2025含 23H2 / 22H2 沿用文档定位架构白皮书深度。读完后应能在不查文档的前提下复述 S2D 内部数据单位与跨节点条带化逻辑。写作约定本文严格区分微软官方硬性表述、微软隐含 / 默认行为、基于已公开文档的推断。不写必须/一定/官方禁止等未经原文支持的绝对化措辞。目录0. 引言为什么官方文档看起来很简单第 1 层64 MiB Region 与 Slab——真正的数据单位第 2 层Column——故障域感知的条带第 3 层Mirror 的数据块分配第 4 层Parity 的数据块分配第 5 层Fault Domain 多级保护6. Slab 大小估算实战7. Repair 路径详解8. 与 Ceph / vSAN / 传统 RAID 的对比9. 总结0. 引言为什么官方文档看起来很简单如果只看微软官方文档对Mirror镜像、Parity奇偶校验、Mirror-Accelerated ParityMAP的描述会觉得它和传统 RAID 区别不大——Mirror 数据多副本Parity 数据 校验位MAP Mirror 与 Parity 混合但事实上Storage Spaces DirectS2D以及 Azure Local 的底层已经远远不是传统 RAID5/RAID6而更接近 Scale-Out Software Defined StorageSDS例如 Ceph、vSAN、Google Colossus。理解它需要分五层来看层数据单位谁来管理第 1 层64 MiB RegionReFS MAP 迁移单位ReFS第 2 层SlabStorage Spaces 内部映射单位Storage Spaces第 3 层Column跨物理盘的条带位置Storage Spaces第 4 层Fault DomainDisk / Node / Enclosure / RackStorage Spaces Azure Local RAC第 5 层Physical Disk硬件下面逐层展开。第 1 层64 MiB Region 与 Slab——真正的数据单位1.1 大多数人的直觉模型很多人会按下面的层次理解存储栈VM └─ VHDX └─ NTFS / ReFS └─ Block (4 KiB) └─ Disk但进入 Storage Spaces 之后这条链被重新切分VM └─ VHDX └─ ReFS └─ 64 MiB Region ← ReFS MAP 迁移单位 └─ Slab ← Storage Spaces 内部映射单位 └─ Column ← 跨物理盘的条带位置 └─ Physical Disk1.2 两个关键单位(1) 64 MiB RegionReFS 的Mirror-Accelerated ParityMAP在 Mirror 与 Parity 之间迁移数据时以 64 MiB 为最小迁移单位。这是 ReFS 文件系统层面的概念与Block4 KiB / 64 KiB完全不同。它把一个 VHDX 在逻辑上划分为许多 64 MiB 的区块每个区块独立决定当前是放在 Mirror 还是 Parity 上。(2) SlabStorage Spaces 内部把每个 64 MiB Region 再切分成大量Slab。Slab 是 Storage Spaces 的内部映射单位Metadata 保存每个 Slab 位于哪些 Physical Extent。Slab 数量与大小取决于 Pool 中物理磁盘的容量与配置微软公开文档未给出固定的 Slab 大小常数因为它会随盘数、容量自动调整。1.3 Region 与 Slab 的关系示意flowchart TD A[VHDXbr/虚拟磁盘] -- B[ReFS 视角br/64 MiB Region 序列] B -- C[Region 0] B -- D[Region 1] B -- E[Region 2] B -- F[Region N] C -- G[Slab 0] C -- H[Slab 1] C -- I[Slab 2] C -- J[Slab K] G -- K[Physical Extentbr/Column 选取] H -- L[Physical Extentbr/Column 选取] I -- M[Physical Extentbr/Column 选取] J -- N[Physical Extentbr/Column 选取] style A fill:#e1f5ff style B fill:#fff3cd style G fill:#d4edda style K fill:#f8d7da1.4 微软真正管理的是什么把这两层串起来64 MiB RegionReFS 视角 ↓ 切分 多个 SlabStorage Spaces 视角 ↓ 元数据记录 每个 Slab 放在哪几个 Column也就是说微软管理的不是文件、不是 Block、不是 VHDX而是Slab 物理位置表。文件、目录、Block 在这个层面已经被 ReFS 接管。Storage Spaces 只关心64 MiB Region 的第 N 个 Slab现在物理上落在哪些 Column 的哪些盘上副本是否满足是否需要 Repair这一点是后续理解 Mirror / Parity / MAP 的基础——所有的副本轮转、双校验布局、MAP Region Rotation全部发生在 Slab 这一层而不是 Block 层。第 2 层Column——故障域感知的条带2.1 一个常见的误解很多人会直觉地认为Node 一列Column这是完全错误的。微软定义的 Column 是一条 Stripe 在多少块物理盘上展开。换句话说Column 数 一个 Stripe 跨多少块物理盘而不是跨多少 Node。2.2 举例4 Node × 2 SSD 拓扑假设集群有 4 个 Node每个 Node 直连 2 块 SSDNode1 ── SSD1, SSD2 Node2 ── SSD1, SSD2 Node3 ── SSD1, SSD2 Node4 ── SSD1, SSD2如果系统分配Columns 4意味着一个 Stripe 展开在 4 块物理盘上Stripe N ── DiskA | DiskB | DiskC | DiskD而不是Stripe N ── Node1 | Node2 | Node3 | Node4 ← 这是错误理解2.3 Column 的选取流程flowchart TD Start[需要写入一个 Stripe] -- FD[收集故障域信息] FD -- Disk[Disk Fault Domain] FD -- Node[Node Fault Domain] FD -- Enc[Enclosure Fault Domain] FD -- Rack[Rack Fault Domainbr/Azure Local RAC] Disk -- Alg[Column 选取算法] Node -- Alg Enc -- Alg Rack -- Alg Alg -- Filter[过滤同 FD 的盘排除] Filter -- Score[为每个候选盘打分br/负载 / 容量 / 历史] Score -- Pick[挑出 N 个 Column] Pick -- Write[并发写入] style Alg fill:#fff3cd style Pick fill:#d4edda2.4 一个关键推论Node 数 ≠ Column 数。场景Node 数推荐 Columns说明4 Node × 4 SSD44 / 8Columns 可等于盘数也可大于 Node 数4 Node × 8 SSD48跨 8 块盘条带16 Node × 4 SSD1616 / 32RAC 场景 Columns 受 Rack 约束微软官方文档在描述 Mirror / Parity 容量效率时会直接给假设 Columns N这样的前提这与 Node 数不是同一回事。第 3 层Mirror 的数据块如何分配3.1 拓扑假设为便于说明本文接下来默认4 Node × 多 SSD3-way Mirror3.2 直觉会犯的错很多人会以为写入一个 64 KiB Block 时Node1 ── Data A Node2 ── Data A 副本 Node3 ── Data A 副本固定三个 Node。但实际并不是这样。3.3 真实流程Column Set 轮转微软首先计算Column Set——三个互不共享 Fault Domain 的物理盘位置例如Column0 ── Node1 Disk2 Column1 ── Node2 Disk1 Column2 ── Node4 Disk2然后Data A Copy1 → Column0 (Node1 Disk2) Copy2 → Column1 (Node2 Disk1) Copy3 → Column2 (Node4 Disk2)下一块Data BData B Copy1 → Node3 Disk1 Copy2 → Node1 Disk1 Copy3 → Node2 Disk2再下一块Data CData C Copy1 → Node4 Disk1 Copy2 → Node3 Disk2 Copy3 → Node1 Disk2副本位置始终轮转Column Set 每条 Stripe 都不一样。3.4 副本轮转的图示flowchart LR subgraph Stripe1[S1] A1[Data A] -- N1D2[Node1 Disk2] A1 -- N2D1[Node2 Disk1] A1 -- N4D2[Node4 Disk2] end subgraph Stripe2[S2] A2[Data B] -- N3D1[Node3 Disk1] A2 -- N1D1[Node1 Disk1] A2 -- N2D2[Node2 Disk2] end subgraph Stripe3[S3] A3[Data C] -- N4D1[Node4 Disk1] A3 -- N3D2[Node3 Disk2] A3 -- N1D2b[Node1 Disk2] end style Stripe1 fill:#e1f5ff style Stripe2 fill:#fff3cd style Stripe3 fill:#d4edda3.5 轮转的目的热点均衡同一个 Node 不会被连续多个 Stripe 砸中Node IO 均衡每个 Node 上的盘轮流承担写副本Disk IO 均衡避免某一块 SSD 成为写瓶颈微软将这种机制称为Distributed Mirror Placement——分布式副本放置。关键认知Mirror 不是按 Node 固定副本位置而是按 Column Set 轮转副本位置。这是 S2D 区别于传统 RAID1固定盘对最大的算法差异之一。第 4 层Parity 的数据块如何分配4.1 Parity 比 Mirror 复杂Parity奇偶校验的难点在于校验位本身也是数据必须参与轮转否则校验盘会成为热点。4.2 拓扑假设4 NodeDual Parity双校验P Q一个 Stripe 假设为D1 D2 P Q4.3 直觉会犯的错很多人会以为Node1 ── D1 Node2 ── D2 Node3 ── P Node4 ── Q一直固定。4.4 真实流程P、Q 也轮转Stripe1: Node1 ── D1 Node2 ── D2 Node3 ── P Node4 ── Q Stripe2: Node1 ── P ← 校验位跳到 Node1 Node2 ── D3 Node3 ── D4 Node4 ── Q Stripe3: Node1 ── Q ← Q 跳到 Node1 Node2 ── P ← P 跳到 Node2 Node3 ── D5 Node4 ── D64.5 校验位轮转图示flowchart TD subgraph S1[Stripe 1] S1N1[Node1: D1] S1N2[Node2: D2] S1N3[Node3: P] S1N4[Node4: Q] end subgraph S2[Stripe 2] S2N1[Node1: P ← 跳到这里] S2N2[Node2: D3] S2N3[Node3: D4] S2N4[Node4: Q] end subgraph S3[Stripe 3] S3N1[Node1: Q ← 跳到这里] S3N2[Node2: P ← 跳到这里] S3N3[Node3: D5] S3N4[Node4: D6] end S1 -- S2 -- S3 style S2N1 fill:#ffcccc style S3N1 fill:#ffcccc style S3N2 fill:#ffcccc4.6 与传统 RAID 的关系这种思想与RAID5 的 Left Symmetric LayoutP 沿盘组轮转与RAID6 的 Rotating ParityP、Q 双校验位独立轮转在数学层面是一致的。但实现层面完全不同维度传统 RAID5/6S2D Parity控制器单个硬件 RAID 卡软件层Storage Spaces跨服务器故障域单台服务器内的盘Disk / Node / Enclosure / Rack轮转粒度盘级Stripe Fault Domain 联合优化修复来源仅同盘组整个 Pool 的所有盘也就是说S2D 是把RAID5/RAID6 的对称校验思想搬到软件层 跨节点 多故障域。4.7 为什么4 Node 才能用 Parity微软官方对 S2D 的支持矩阵3 Node只能 3-way Mirror4 Node 及以上可以 Mirror也可以 Dual Parity这一点本文不展开技术根因会单独写第三篇但逻辑上的解释是Dual Parity 需要 2 个独立校验位最小 Stripe 2 Data 2 Parity 4 列再叠加 Fault Domain 约束4 Node 是 S2D 默认推荐的最小 Parity 拓扑。第 5 层Fault Domain——为什么多节点越多越复杂5.1 故障域的种类Storage Spaces 在做 Column 选择时会同时考虑多个故障域层级故障域是否存在典型场景Disk始终存在任何硬盘NodeS2D / Azure Local节点宕机 / 重启 / 维护Enclosure部分硬件JBOD、ChassisRackAzure Local RAC 2510机架级故障电源、网络5.2 RAC 引入 Rack Fault Domain到了 Azure Local 2510 的 Rack Aware Cluster微软又增加了一层约束Rack A ├─ Node1 └─ Node2 Rack B ├─ Node3 └─ Node4Column 选择从以前的避开同 Node扩展为避开同 Node 同 Rack。每个 Stripe 的 Column 分配会同时考虑Disk Failure磁盘故障Node Failure节点宕机Chassis Failure机箱故障Rack Failure机架故障Column 的选择已经从单纯的磁盘条带演进为面向多级故障域的智能布局——这是 Azure Local 相比传统 RAID 控制器最大的架构差异。5.3 RAC 故障域示意图flowchart TB subgraph RackA[Rack A] N1[Node1br/Disk 1-4] N2[Node2br/Disk 1-4] end subgraph RackB[Rack B] N3[Node3br/Disk 1-4] N4[Node4br/Disk 1-4] end subgraph RackC[Rack C] N5[Node5br/Disk 1-4] N6[Node6br/Disk 1-4] end Stripe[Stripebr/Columns6] -- N1 Stripe -- N3 Stripe -- N5 Stripe -- N2 Stripe -- N4 Stripe -- N6 style RackA fill:#ffe4e1 style RackB fill:#e0f7fa style RackC fill:#f1f8e9 style Stripe fill:#fff3cd5.4 一个容易踩的坑Fault Domain 配错会直接锁死 Column例如一个 4 Node 集群如果物理上 Node1 和 Node2 在同一 Rack但 RAC 配置没有声明 Rack Fault Domain那么 Column 选择只会避开 Node而不会避开 Rack——一旦这个 Rack 整体掉电交换机 / PDU 故障数据可能因两个副本恰好在同一 Rack而不可恢复。因此 Azure Local RAC 部署时正确声明 Fault Domain 拓扑是数据可靠性的硬性前提不是建议。6. Slab 大小估算实战6.1 为什么估算 Slab 大小Slab 大小直接决定Metadata 表的条目数影响内存与启动速度Repair 粒度影响重建性能单次 IO 跨多少块盘知道 Slab 大小有助于调优 Pool。6.2 微软公开的 Slab 规则微软在公开文档中给出过一个经验公式属于基于已公开文档的推断不是精确数学公式Slab 大小 ≈ Pool 总容量 / 物理盘数 / 某个常数实际经验在小规模 Pool 100 TB中Slab 通常在256 MiB ~ 1 GiB范围在大规模 Pool 500 TB中Slab 会被进一步切分6.3 影响 Slab 大小的因素因素影响物理盘数越多 → Slab 越小Metadata 越多单盘容量越大 → Slab 越大启用 Nested Resiliency双层 ResiliencySlab 重新划分Performance History算法根据访问模式动态调整6.4 通过 PowerShell 查看 Slab 信息# 查看 Pool 的 Slab 配置部分字段需要 Windows Server 2022 Get-StoragePool -FriendlyName S2DPool | Format-List * # 查看 Virtual Disk 的 Column 数 Get-VirtualDisk | Select-Object FriendlyName, NumberOfColumns, ResiliencySettingName # 查看每个盘的 Physical Extent 分布 Get-PhysicalDisk | Get-Disk | Get-Partition | Get-Volume说明微软未公开完整的 Slab 大小计算公式上面只是经验范围不写权威数字。7. Repair 路径详解7.1 Repair 是什么当一块盘或一个 Node 出现故障后Storage Spaces 会从 Pool 内其他健康的盘读取副本/校验数据重新生成丢失的副本并写入新的位置——这个过程叫Repair。7.2 Repair 的两种场景场景触发条件重建来源Disk Repair单盘坏同 Pool 内其他盘Node Repair整机宕机同 Pool 内其他 Node7.3 Repair 的流程sequenceDiagram participant Disk as 故障盘 participant Meta as Pool Metadata participant Src as 源盘健康副本 participant Dst as 目标盘写入新副本 participant App as 前端应用 Disk-Meta: 检测到故障 / 标记 offline Meta-Meta: 列出该盘上所有 Slab loop 每个 Slab Meta-Src: 读取现有副本Mirror 或 Parity 重算 Src--Meta: 返回数据 Meta-Dst: 写入新副本 Dst--Meta: ACK Meta-Meta: 更新 Metadata end Meta-App: 通知 Repair 完成7.4 Repair 的关键认知(1) Repair 的源数据可以是任意健康盘不像传统 RAID 只能从同盘组修复S2D 可以从整个 Pool 任意盘读源数据。这就是Every Drive is a Spare。(2) Repair 是后台任务Repair 默认是后台异步执行不阻塞前端 IO但会消耗 IO 带宽可能影响业务性能。(3) 多个盘同时故障的 Repair 顺序微软按重要数据先修的策略但具体排序算法未公开。(4) Azure Local 上的 Repair 加速Windows Server 2022 起Azure Local 上的 Repair 速度比传统 S2D 更快微软未公开具体加速比不写绝对数字。8. 与 Ceph / vSAN / 传统 RAID 的对比维度传统硬件 RAIDS2D / Azure LocalCephVMware vSAN数据单位LBA / StripeSlab 64 MiB RegionObject PGComponent副本位置固定盘对Column 轮转CRUSH 哈希RAID-1/5/6 策略校验位固定盘P、Q Stripe 轮转Jerasure / ISA-LRAID-5/6 擦除故障域单台服务器Disk / Node / Enclosure / RackHost / Rack / RoomHost / RackMetadataRAID 卡 NVRAMPool Metadata 全局OSD Map PG LogDOM Witness修复来源同盘组热备整个 Pool整个 Cluster整个 Cluster横向扩展不支持原生 2~16 Node无理论上限推荐 2~64 HostPlacement 算法静态动态 Fault DomainCRUSH 哈希策略 Witness结论S2D 在数据布局算法上接近 Ceph / vSAN都是元数据驱动的分布式放置但缺少 Placement Group 这类局部修复机制全局 Metadata 是它的最大瓶颈。9. 总结flowchart TD A[VM 写入请求] -- B[ReFSbr/64 MiB Region 划分] B -- C[Storage Spaces Metadata] C -- D[Slab Mappingbr/查找物理位置] D -- E[Column Selectionbr/Fault Domain Aware] E -- F1[Mirror: 三副本轮转] E -- F2[Parity: P Q 轮转] E -- F3[MAP: 先 Mirror 后 Rotate] F1 -- G[Physical Disk] F2 -- G F3 -- G style A fill:#e1f5ff style B fill:#fff3cd style E fill:#d4edda style G fill:#f8d7da9.1 与传统 RAID 的本质差异维度传统 RAIDStorage Spaces / S2D数据单位LBA / StripeSlab 64 MiB Region副本位置固定盘对动态 Column 轮转校验位固定盘P、Q 都参与 Stripe 级轮转故障域单台服务器Disk / Node / Enclosure / RackMetadataRAID 卡 NVRAM全局 Pool Metadata修复来源同盘组热备整个 Pool 任意盘横向扩展不支持原生支持 2~16 Node9.2 与分布式 SDS 的相似性正因为这套机制——Slab、Column 轮转、Fault Domain Aware、Pool 级 Metadata——S2D 才被普遍认为更接近CephCRUSH PG、VMware vSANRAID-5/6 擦除编码、Google Colossus而不是传统 RAID数据布局是由元数据驱动的分布式放置算法决定的而不是固定 RAID 条带或固定磁盘顺序。这也是为什么本文把它叫作五层数据布局原理——微软文档不写 Slab、不写 Column 轮转算法、不写 Fault Domain 权重是因为这些实现细节在官方层面属于内部行为但它们恰恰是理解 S2D 性能、容量、修复行为的关键。10. 后续阅读第二篇Mirror / Parity / MAP 数据流与 Region Rotation 的细节第三篇为什么 3 节点必须 3-way Mirror、4 节点才能用 Parity、为什么单校验被淘汰第四篇Windows Server 2025 在 Storage Spaces 上做了什么、没做什么以及下一代方向预测