上一篇 下一篇 分享链接 返回 返回顶部

香港服务器使用 Windows Server 2022 时,如何把 S2D(Storage Spaces Direct)“拧到顶”,把 IOPS 真正抬起来

发布人:Minchunlin 发布时间:2025-08-19 09:14 阅读量:744


夜里 2:17,香港机房的冷风像一条直冲的风道,从脚边一直吹到后颈。香港这座楼的电梯严格分区,安全员每次都要看一眼我的工牌才按下 B3。电话那头客户的句子很短——“VM 抖、数据库卡、IO 等不及。” 我看着机柜门上贴的工单,心里已经有了大致的路线:把这套四节点的 Windows Server 2022 + Storage Spaces Direct (S2D) 从“能跑”调成“会跑”,把 IOPS 拉上去,让 99 百分位的延迟老实下来。以下,就是我在现场一步步做的事、遇到的坑、以及每一步背后的理由。

现场清单(真实场景的“家底”)

类别 参数/型号 数量/说明
机房 香港葵涌某 DC,双路市电 + 2N UPS,冷热通道分离 1 组
集群规模 4 节点 S2D(超融合) 4 台
服务器 2U 双路(Xeon/EPYC 均可),BIOS 设为 Performance 模式 4 台
内存 512 GB/节点 4
系统盘 2 × SATA SSD (RAID1) 做 OS 每节点
NVMe(缓存层) U.2 NVMe 3.2 TB × 6/节点(BusType=NVMe) 24 块
SATA SSD(容量层) 7.68 TB × 10/节点(BusType=SATA) 40 块
网卡(数据/存储) 2 × 100GbE RDMA(Mellanox ConnectX-5/6 级别) 每节点
交换机 100GbE ToR ×2(MLAG 堆叠,支持 DCB/PFC/ETS) 2 台
OS Windows Server 2022 Datacenter (最新累积补丁) 全节点
文件系统 CSVFS_ReFS(卷内 64K Allocation Unit) S2D 卷
虚拟化 Hyper-V(部分客户是裸机 K8s on VM) 视业务

这套盘型是典型 NVMe+SATA SSD 的全闪 组合:NVMe 做 Cache(写回+读热点)、SATA SSD 做容量。目标是把随机 4K 读写/混合 IOPS 和 P999 延迟稳住,同时维持有效容量与恢复速度的平衡。

思路地图(先讲策略,再敲命令)

先把“能快速误伤性能”的项排干净:BIOS 节能/ASPM、NIC 的 Jumbo/RDMA、DCB/PFC、交换机 QoS、驱动固件版本。

再做 S2D 的结构性选择:布局(3 副本镜像 vs 镜像加速奇偶)、列(Columns)与条带(Interleave),以及 Cache 的状态。

最后是 Windows 层面的“细刀功”:CSV 只读缓存、ReFS 完整性流、Dedup 计划、SMB Direct/Multi-Channel 细节、RSS/CPU 亲和。

步骤一:硬件与固件的“地基”校准

1) BIOS/平台电源策略

  • Power:Performance / Maximum Performance
  • C-State/Package C-State:Disabled
  • PCIe ASPM:Disabled
  • NUMA:保持默认(不要跨 NUMA 的 BIOS“优化”)
  • SR-IOV:Enabled(通常对虚拟化友好)
  • 目的:避免省电策略带来的微抖动,尤其是 RDMA 和 NVMe 对尾延迟很敏感。

2) 网卡与交换机的“共识”

端到端 Jumbo:9000(有些驱动是 9014),交换机接口 MTU 与服务器一致,不一致宁可先关掉 Jumbo 做 A/B 测。

RDMA 类型:RoCEv2(需要 DCB/PFC),或 iWARP(无需 PFC)。本现场为 RoCEv2。

DCB 策略(关键):

仅对 Priority 3 开启 PFC(SMB Direct 常用优先级),其他优先级全部关闭 PFC,避免全网“堵车”(Pause Storm)。

ETS 给 SMB 类流量 50–60% 带宽权重,避免 VM East-West 打爆 RDMA 通道。

交换机 ECN/队列门限跟 NIC 保持一致或由网络组按经验值下发。

步骤二:Windows 网络栈(PowerShell 操作)

以下命令在 每个节点 执行。网卡名示例 "NIC1","NIC2",按你实际命名替换。

# 基础功能
Install-WindowsFeature -Name Data-Center-Bridging, RSAT-Clustering-PowerShell -IncludeManagementTools

# 开启 QoS/DCB 基础
Enable-NetAdapterQos -Name "NIC1","NIC2"
New-NetQosTrafficClass -Name "SMB" -Priority 3 -BandwidthPercentage 60 -Algorithm ETS

# 只在 P3 开启 PFC,其余优先级一律关闭
Enable-NetQosFlowControl -Priority 3
Disable-NetQosFlowControl -Priority 0,1,2,4,5,6,7

# 把 TCP/445(SMB)打上优先级 3
New-NetQosPolicy -Name "SMB" -NetDirectPortMatchCondition 445 -PriorityValue8021Action 3

# 让主机不“被交换机修改意愿”
Set-NetQosDcbxSetting -Willing $false -Confirm:$false

# Jumbo(如有需要)
Set-NetAdapterAdvancedProperty -Name "NIC1","NIC2" -DisplayName "Jumbo Packet" -DisplayValue "9014 Bytes"

# RDMA/Multi-Channel
Enable-NetAdapterRdma -Name "NIC1","NIC2"
Set-SmbClientConfiguration -EnableMultiChannel $true -EnableBandwidthThrottling $false
Set-SmbServerConfiguration -EnableSMBDirect $true -RejectUnencryptedAccess $false

# RSS(避免单核瓶颈)
Set-NetAdapterRss -Name "NIC1","NIC2" -MaxProcessors 16

# 可选:关闭 RSC(有些驱动+流量形态下更稳)
Set-NetAdapterAdvancedProperty -Name "NIC1","NIC2" -RegistryKeyword "*RscIPv4" -RegistryValue 0
Set-NetAdapterAdvancedProperty -Name "NIC1","NIC2" -RegistryKeyword "*RscIPv6" -RegistryValue 0

# 验证
Get-NetAdapterRdma
Get-SmbMultichannelConnection

常见坑:

  • Jumbo 只配了一半(交换机/服务器不一致)→ 碎包重组,反而更慢。
  • 把 全优先级 开了 PFC → 轻松复刻“全网停车场”。
  • RSS 没开或队列太少 → CPU 单核拉满,IOPS 上不去。

步骤三:S2D 建栈与布局(决定你的 IOPS 上限)

1) 建群/拉起 S2D

# 基础角色
Install-WindowsFeature -Name Failover-Clustering, FS-FileServer -IncludeManagementTools

# 健康检查(建议把报告留档)
Test-Cluster -Node HK-S2D01,HK-S2D02,HK-S2D03,HK-S2D04 | Out-File C:\temp\cluster-validation.txt

# 建群(示例 IP 替换)
New-Cluster -Name HK-S2D `
  -Node HK-S2D01,HK-S2D02,HK-S2D03,HK-S2D04 `
  -StaticAddress 10.10.0.10 -NoStorage

# 打开 S2D(NVMe 作为缓存,自动识别)
Enable-ClusterS2D -CacheState Enabled -Confirm:$false

要点:混合介质(NVMe + SATA SSD)场景,S2D 会自动把 NVMe 放在 Cache 层;全 NVMe 时通常 关闭 Cache(或让其自动为只读)。Windows Server 2022 的自动策略已经很成熟,除非你非常确定自己要手动改。

2) 卷/条带参数(Columns & Interleave)

Columns(条带列数)决定请求 fan-out 的“宽度”。NVMe 数量 × 节点数的 50–80% 通常是一个起点,避免过高导致写放大与重构压力。

Interleave 建议 256KB(262144),与 ReFS/SMB 的典型 IO 对齐友好。

方案 A:3 副本镜像(高 IOPS、占用大)

$pool = Get-StoragePool -FriendlyName "S2D on HK-S2D"

New-Volume -StoragePoolFriendlyName $pool.FriendlyName `
  -FileSystem CSVFS_ReFS -FriendlyName "VD-3W" `
  -Size 20TB -ResiliencySettingName Mirror `
  -NumberOfDataCopies 3 -ProvisioningType Fixed `
  -AllocationUnitSize 65536 -NumberOfColumns 8 -Interleave 262144

方案 B:镜像加速奇偶(MAP,容量友好、性能折中)

$pool = Get-StoragePool -FriendlyName "S2D on HK-S2D"

# 建两个层:高速镜像层 + 容量奇偶层(同为 SSD 媒体,NVMe 由 S2D 作 Cache)
$mirror = New-StorageTier -StoragePoolFriendlyName $pool.FriendlyName `
  -FriendlyName "PerfMirror" -MediaType SSD -ResiliencySettingName Mirror `
  -NumberOfDataCopies 3

$parity = New-StorageTier -StoragePoolFriendlyName $pool.FriendlyName `
  -FriendlyName "CapParity" -MediaType SSD -ResiliencySettingName Parity `
  -PhysicalDiskRedundancy 2

# 用 30% 镜像 + 70% 奇偶 做一个加速卷(按业务调整)
New-Volume -StoragePoolFriendlyName $pool.FriendlyName `
  -FriendlyName "VD-MAP" -FileSystem CSVFS_ReFS `
  -StorageTierFriendlyNames "PerfMirror","CapParity" `
  -StorageTierSizes 6TB,14TB -AllocationUnitSize 65536 `
  -ProvisioningType Fixed -NumberOfColumns 8 -Interleave 262144

经验:强交易/小块随机写 → 选 3 副本镜像;镜像加速奇偶 适合偏读多、顺序多、或冷热明显的混部场景。测试不一致就多做两组 A/B。

步骤四:Windows 层面的“细刀功”

1) CSV 读缓存(Block Cache)

# 全局缓存池大小(例:4GB)
Get-Cluster | Set-ClusterParameter -Name SharedVolumeBlockCacheSizeInMB -Value 4096

# 每个 CSV 打开缓存
Get-ClusterSharedVolume | Set-ClusterParameter -Name CsvEnableBlockCache -Value 1

纯随机写帮助有限,但对混合/读主导有时能压下 P95/P99 的毛刺。

2) ReFS 完整性流(Integrity Streams)

对 VM VHDX/数据库数据卷,建议关闭完整性流减少元数据校验开销,但日志/备份卷可以保留。

# 关闭目标目录的完整性(示例路径替换)
Set-FileIntegrity "C:\ClusterStorage\Volume1\VMs" -Enable $false

3) 重删(Dedup)与计划

Windows Server 2022 对 ReFS + Hyper-V 的重删已很成熟,但它吃 CPU/内存,务必设好计划窗口。

Enable-DedupVolume -Volume "C:\ClusterStorage\Volume1" -UsageType HyperV
# 夜间 0:00-6:00 优化
Set-DedupSchedule -Type Optimization -ActiveHoursStart 0:00 -ActiveHoursEnd 06:00 `
  -Days Monday,Tuesday,Wednesday,Thursday,Friday

4) SMB Multichannel“约束”(可选)

当 RDMA + 100G 足够时,可以限制多通道仅走 RDMA 接口,避免跑到非 RDMA 的管理网卡:

# 删掉旧约束
Get-SmbMultichannelConstraint | Remove-SmbMultichannelConstraint -Confirm:$false
# 只允许 NIC1/NIC2 参与
New-SmbMultichannelConstraint -InterfaceIndex (Get-NetAdapter "NIC1").ifIndex -ServerName "*"
New-SmbMultichannelConstraint -InterfaceIndex (Get-NetAdapter "NIC2").ifIndex -ServerName "*"

步骤五:基准与验证(给数字说话)

我用 DiskSpd 做了三组 60 秒跑分,关闭软硬件缓存、拉延迟分位数。测试文件放在 C:\ClusterStorage\Volume1\bench\test.dat。

# 4K 随机读(典型 OLTP 读)
.\diskspd.exe -b4K -d60 -o32 -t8 -r -w0 -Sh -L -c200G C:\ClusterStorage\Volume1\bench\ro.dat

# 4K 随机 70/30 读写(混合)
.\diskspd.exe -b4K -d60 -o32 -t8 -r -w30 -Sh -L -c200G C:\ClusterStorage\Volume1\bench\rw.dat

# 64K 顺序读(备份/流媒体)
.\diskspd.exe -b64K -d60 -o4 -t8 -Sh -L -c400G C:\ClusterStorage\Volume1\bench\seq.dat

调优前 vs 调优后(3 副本镜像卷)

场景 IOPS(前) IOPS(后) P99 延迟(前) P99 延迟(后)
4K 随机读 680,000 1,750,000 5.8 ms 1.9 ms
4K 随机 70/30 420,000 980,000 7.2 ms 2.8 ms
64K 顺序读(MB/s) 9,500 18,200 6.1 ms 2.4 ms

这些数字不是“广告词”,它跟你的 NVMe 代际、列条带、RDMA 稳定度、后台任务 强相关。关键是方法论:同一套数据集,每改一项做 A/B;看 IOPS、P99、CPU 利用、RDMA 端口计数器、丢包 一起变不变。

在现场踩的坑 & 解决过程

  • PFC 开太多:一开始交换机把 0–7 全开了 PFC,RDMA 端口偶发 Pause Storm。解决:只留 Priority 3;关掉其他优先级的 PFC;ETS 明确配额。
  • Jumbo“半开”:ToR 开 9216,服务器一个节点忘了改,那个节点的 SMB Direct 连接 P99 飙高。解决:先全关 Jumbo 做对照基线;再端到端一致打开。
  • NVMe Firmware 混版:两家厂商、三个固件版本,Log 里能看到写延迟离群。解决:统一固件;S2D 的修复速度明显提升。
  • ReFS Integrity Streams:默认开启对小 IO 成本不小,VHDX 卷随机写 P99 出现毛刺。解决:对数据热路径目录关掉完整性流,仅日志/备份卷保留。
  • Dedup 抢资源:白天跑重删,Hyper-V 主机 CPU 抽风。解决:把 Dedup 优化窗口放到 0:00–6:00,周末加长,工作日压缩。
  • Columns 过大:为了“更宽的条带”设到 12,重构/修复时 IOPS 掉得更狠。解决:回到 8 列,峰值 IOPS 差不多,但稳定性更好。
  • SMB 走错网:少数连接跑去管理网卡(非 RDMA)。解决:用 SmbMultichannelConstraint 绑定在存储网络。

运行期看什么(健康与可视化)

# S2D 健康
Get-StorageSubSystem -FriendlyName "Clustered Storage Spaces*" | Get-StorageHealthReport

# 物理盘/故障域
Get-PhysicalDisk | ft FriendlyName,HealthStatus,BusType,MediaType,Size

# NVMe 热点(Cache 命中率/写回队列)
Get-StorageTier | ft FriendlyName,MediaType,ResiliencySettingName,ReadCacheReservation,WriteCacheSize

# SMB Direct 连接 & RDMA 计数
Get-SmbMultichannelConnection
Get-NetAdapterRdma | ft Name,Enabled

# CSV 缓存状态
(Get-Cluster).SharedVolumeBlockCacheSizeInMB
Get-ClusterSharedVolume | Get-ClusterParameter CsvEnableBlockCache

告警习惯:

  • NVMe 温度/掉线(大热天搬风/挡板缺失会出事);
  • RDMA 端口丢包/重传(ECN/PFC 是否异常);
  • Rebuild 时段与业务峰值错开(S2D 能控节流,但要有人盯)。

不同卷布局的“账本”

布局 有效容量系数 小块随机写 IOPS 重构速度 适用场景
3 副本镜像 1/3 最高 OLTP/虚拟化热盘、交易写密集
镜像加速奇偶(MAP) ~0.6–0.7(取决于比例) 高(热写进镜像)/冷下滑 混合负载、冷热分明
纯奇偶(不建议) ~0.8 追求极致容量,性能需求弱

我的“默认模板”(可直接落地的步骤表)

  1. 固件/驱动:统一版本 → BIOS Performance → 关 C-State/ASPM。
  2. 交换机策略:DCB/ETS/PFC 仅开 P3 → MTU 一致。
  3. 主机网络:启 DCB/RDMA/Jumbo(或全关)→ RSS=16 → 限定 SMB 通道。
  4. S2D:Enable-ClusterS2D → 先做一个 3 副本镜像卷(20TB),Columns=8, Interleave=256KB,跑基线。
  5. Windows 优化:CSV Cache 4GB、业务目录关 Integrity、重删只跑夜间。
  6. 基准:三套 DiskSpd 脚本,记录 IOPS/P99/CPU;只改一项做 A/B。
  7. 扩展:按业务加 MAP 卷,镜像:奇偶 ≈ 30:70 起步,再调。

FAQ(我现场最常被问到的)

Q:为什么不一上来就用 MAP?

A:排障/建模需要“纯净基线”。先用 3 副本镜像把网络+Cache+文件系统打穿,得到可预期的性能上限,再引入 MAP 权衡容量。

Q:Jumbo 一定更快吗?

A:不一定。一致性 比绝对 MTU 更重要。端到端不一致/中间设备不支持时,Jumbo 会适得其反。

Q:ReFS Integrity Streams 关了安全吗?

A:我只在 热数据/高并发写路径 关,日志/备份/归档 仍开。配合稳定电力与宿主完整性校验,风险可控。

Q:Columns 设多少合适?

A:跟你的 物理盘并发/节点数/修复窗口 强相关。我的经验是 NVMe×节点数的 50–80% 起步,再用 A/B 验证。

收尾:一阵风过,指示灯在说话

凌晨 4:05,客户那边的业务监控曲线变得顺滑了——那条曾经像海潮一样起伏的延迟线压进了 2–3ms 的区间。机柜前的指示灯有节律地闪,我把最后一条 Get-StorageHealthReport 保存进工单,关上前门,再摸一摸那条刚贴上的标签:“P3 仅开 PFC,别全开。”
走回电梯时,天刚蒙亮。香港的空气里混着海味和一点点金属的凉。我知道,下次再有人说“IO 抖”,我会从同一套方法论开始,但落在每个机房的手感,还是得靠亲手去拧——拧到所有数字都点头为止。

附:可直接粘贴的检查脚本(汇总)

# Net/RDMA 快速体检
Write-Host "=== RDMA/MultiChannel ==="
Get-NetAdapterRdma
Get-SmbMultichannelConnection

Write-Host "=== DCB/PFC/ETS ==="
Get-NetQosTrafficClass
Get-NetQosFlowControl
Get-NetQosPolicy

Write-Host "=== Jumbo/RSS ==="
Get-NetAdapterAdvancedProperty -Name "NIC1","NIC2" | ?{$_.DisplayName -match "Jumbo"}
Get-NetAdapterRss -Name "NIC1","NIC2"

Write-Host "=== S2D Health ==="
Get-StorageSubSystem -FriendlyName "Clustered Storage Spaces*" | Get-StorageHealthReport

Write-Host "=== CSV Cache ==="
(Get-Cluster).SharedVolumeBlockCacheSizeInMB
Get-ClusterSharedVolume | Get-ClusterParameter CsvEnableBlockCache

Write-Host "=== ReFS Integrity (示例) ==="
Get-ChildItem C:\ClusterStorage\Volume1\VMs -Directory | % { 
  Get-FileIntegrity $_.FullName 
}

如果你也在香港的某个机房里对着 S2D 发愁,按这篇文章的顺序走一遍:先统一地基,再定布局,最后细刀功。IOPS 会给你回消息的。

目录结构
全文