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

如何在香港服务器运行 Windows Server 时,把 RDMA 和 SQL AlwaysOn 结合起来,压低金融交易库的响应延迟

发布人:Minchunlin 发布时间:2025-09-07 12:38 阅读量:685


夜盘刚收,我站在香港葵涌那排机柜前,盯着监控墙上那条“撮合库 P99 写入延迟”曲线——行情放量时总会偶尔抬头。白天的交易窗口不允许试错,我只有这一夜的维护窗把延迟再压一截。

这篇文章是那一夜到上线后的完整记录:硬件选型、RDMA(SMB Direct)的布线与配置、Windows/交换机的 DCB/QoS、SQL Server AlwaysOn 可用性组的搭建、压测与指标对比、以及几个在现场踩过的坑。它不止是“怎么做”,也包含“为什么这么做”。

目标与边界

目标:在不改变业务 SQL 语义的前提下,降低交易库的写入与同步路径延迟,稳定早盘/尾盘放量时的 P99/P99.9。

核心手段:

  • 利用 RDMA(RoCEv2)+ SMB Direct 加速备份/还原、自动播种(direct seeding 辅助场景)、日志/快照落盘到 SOFS(Scale-Out File Server)等基于 SMB 的数据流;
  • SQL Server AlwaysOn 可用性组(AG) 做高可用/读写分离:同城(机房内)同步提交 + 自动故障转移;异地(可选)异步提交作为只读灾备;
  • 把数据平面与管理/客户端平面彻底隔离,对 RDMA 通道做 DCB(PFC/ETS)与队列调度,保证流量无损、低抖动。

非常重要的边界认知:AG 的数据复制走的是数据库镜像端点(TCP/5022),不是 RDMA。

我们把 RDMA 用在 SMB3/SMB Direct 的链路上(例如自动播种文件、备份/还原到 SOFS、S2D/CSV、日志落盘到远端文件服务器等),以及剥离 AG 之外的重 I/O 流。这能明显减少 CPU 抢占与网络抖动,缩短“总体”收敛时间,间接改善峰值时段的写入等待与 redo 队列。

现场硬件与拓扑

服务器与网络(实配示例)

角色 型号/CPU 内存 磁盘 NIC(RDMA) OS SQL
HKSQL1/2(主/同步副本) Dell R650, Xeon Gold 6338N(32C) 512 GB 8× NVMe PM1733 3.84TB(RAID10 for data, RAID1 for log) Mellanox ConnectX-5 25GbE ×2(RoCE v2)+ 10GbE 管理口 Windows Server 2022 Datacenter SQL Server 2022 Enterprise
HKSQL3(只读/异步灾备) 同上 512 GB 同上 同上 同上 同上
SOFS01/02(文件服务器集群,S2D) Dell R650 512 GB 20× NVMe + 2× SSD Cache(S2D) ConnectX-5 25GbE ×2 Windows Server 2022 Datacenter FS-Role

交换机:叶-脊两层,Arista 7050X3(25/100GbE),开启 DCB(PFC on 3)、ETS,全链路 MTU 9216。

布线:

  • RDMA/SMB 网络(VLAN 200):HKSQL1/2/3 与 SOFS01/02 双上联到叶交换,LACP 聚合;
  • 客户端/业务网络(VLAN 10):交易应用与 AG Listener;
  • 管理网络(VLAN 99):BMC、域控、跳板等。

不要让 SMB/AG/管理混杂一条线,这会在放量时出现“看不见”的队列争用。

设计要点(为什么这么搭)

  • AG 同步提交只用于机柜内的 HKSQL1/2:保证毫秒级 RTT;
  • 异步副本 HKSQL3 面向报表/风控,只读;
  • 备份/播种/大体量文件流 走 SMB Direct(RDMA) 到 SOFS:释放 SQL 进程 CPU,缩短维护窗;
  • QoS/ETS 给 SMB(优先级 3)保底带宽,PFC 保证无丢包,RDMA 零拷贝减少延迟抖动;
  • Jumbo Frame 端到端一致,避免 MTU 不对齐导致的隐形重传;
  • Listener 与 DNS 定位 固定在客户端网络,避免客户端误打到 RDMA 平面。

步骤一:Windows 与 NIC 的 RDMA/队列配置

以下以 Mellanox ConnectX-5 + Windows Server 2022 为例。请根据驱动版本适当调整属性名。

1. 打开 RDMA、多队列、巨帧(两台 SQL、两台 SOFS 全都做)

# 查看并启用 RDMA
Get-NetAdapterRdma
Enable-NetAdapterRdma -Name "RDMA1","RDMA2"

# 打开 RSS / 动态中断
Enable-NetAdapterRss -Name "RDMA1","RDMA2"

# 统一 MTU(先从交换机到服务器端口统一 9216)
# Mellanox 驱动通常通过高级属性 *JumboPacket
Set-NetAdapterAdvancedProperty -Name "RDMA1" -RegistryKeyword "*JumboPacket" -RegistryValue 9014
Set-NetAdapterAdvancedProperty -Name "RDMA2" -RegistryKeyword "*JumboPacket" -RegistryValue 9014

# 为 Mellanox 设定 RoCE v2(若默认 v1)
Set-NetAdapterAdvancedProperty -Name "RDMA1" -DisplayName "RoCE mode" -DisplayValue "RoCE v2"
Set-NetAdapterAdvancedProperty -Name "RDMA2" -DisplayName "RoCE mode" -DisplayValue "RoCE v2"

2. DCB/QoS(PFC + ETS)

# 开启 NIC 级 QoS/DCB
Enable-NetAdapterQos -Name "RDMA1","RDMA2"

# 为 SMB Direct 指定 802.1p 优先级 3(NetDirect = 445)
New-NetQosPolicy -Name "SMB-Direct" -NetDirectPortMatchCondition 445 -PriorityValue8021Action 3

# 启用 PFC:只对优先级 3 开;其它优先级关掉,避免“全链路暂停风暴”
Enable-NetQosFlowControl -Priority 3
Disable-NetQosFlowControl -Priority 0,1,2,4,5,6,7

# ETS:保证 SMB 至少 60% 带宽(根据业务占比调整)
New-NetQosTrafficClass -Name "SMB" -Priority 3 -BandwidthPercentage 60 -Algorithm ETS

交换机侧(示意,Arista 风格)

dcbx application priority ethernet 3 smb
priority-flow-control priority 3 enable
priority-flow-control no-drop
priority-group 3 bandwidth 60 pfc on
interface Ethernet1-32
  mtu 9216
  priority-flow-control on
  spanning-tree portfast

关键点:端到端一致——服务器/交换机的 PFC、ETS、MTU 必须闭环一致,否则 RDMA 要么不上路,要么不稳定。

3. SMB Multichannel/Direct 检查

# 确认 SMB Multichannel 与 Direct 已启用(默认启用)
Set-SmbServerConfiguration -EnableSMBMultichannel $true -Force
Set-SmbClientConfiguration -EnableMultiChannel $true

# 约束 SMB 只走 RDMA 接口(可选,但强烈建议)
# 先取 RDMA 网卡的 InterfaceIndex
Get-NetAdapter | ft Name,InterfaceDescription,InterfaceIndex
New-SmbMultichannelConstraint -InterfaceIndex 12,13  # RDMA1/2 的 Index

验证 RDMA 是否真正生效(两端都看):

# 在客户端(SQL 服务器)上连到 SOFS 后查看多通道连接
Get-SmbMultichannelConnection | ft ServerName,ClientInterfaceIndex,Rdma,ClientRSS,ServerRSS,State

# 网络接口能力
Get-SmbClientNetworkInterface | ft InterfaceIndex,RdmaCapable,RssCapable,LinkSpeed

看到 Rdma = True 才算成功;否则多半是 PFC/ETS/MTU/路径不一致导致的“看起来通了,实际上没走 RDMA”。

步骤二:Windows 集群与 SOFS(SMB Direct 的落脚点)

域控/证书/时间:两台 SQL、两台 SOFS 全部入域,时间同步;

创建 WSFC:把 SOFS01/02 先组为一个 文件服务器集群(Scale-Out File Server),导出共享:

\\sofs\sqlbackups(备份/还原/日志归档)

\\sofs\seeding(大库首播种临时文件)

共享权限:SQL Server 服务账号(域账号)授予 Full Control;SMB 高可用由 SOFS 提供,SMB 客户端(SQL)自动多通道 + RDMA。

步骤三:SQL Server AlwaysOn 可用性组

前提:三台 SQL 已安装 SQL Server 2022 Enterprise,同一域,启用 Windows Server Failover Clustering 功能;数据库 TradingDB 已就绪。

1. 打开 HADR、端点与防火墙

-- 三台都执行
EXEC sys.sp_configure N'contained database authentication', 1;
RECONFIGURE WITH OVERRIDE;

-- HADR 端点(TCP 5022)
CREATE ENDPOINT [Hadr_endpoint]
   STATE=STARTED
   AS TCP (LISTENER_PORT = 5022)
   FOR DATABASE_MIRRORING (ROLE = ALL, ENCRYPTION = REQUIRED, ALGORITHM = AES);
GO

# Windows 防火墙(入站 5022、出入 445、客户端 1433)
New-NetFirewallRule -DisplayName "SQL HADR 5022" -Direction Inbound -Protocol TCP -LocalPort 5022 -Action Allow
New-NetFirewallRule -DisplayName "SMB 445" -Direction Inbound -Protocol TCP -LocalPort 445 -Action Allow
New-NetFirewallRule -DisplayName "SQL 1433" -Direction Inbound -Protocol TCP -LocalPort 1433 -Action Allow

在域环境里,AG 端点通常用 Windows 身份验证(服务账号),避免证书错配的问题。

2. (可选)利用 SMB Direct 做“首播种”/大库迁移

-- 主库上先备份到 SOFS(走 RDMA 的 SMB)
BACKUP DATABASE [TradingDB]
  TO DISK = N'\\sofs\seeding\TradingDB_full.bak'
  WITH COMPRESSION, CHECKSUM, STATS=5;

-- 备库上从 SOFS 还原到 NORECOVERY
RESTORE DATABASE [TradingDB]
  FROM DISK = N'\\sofs\seeding\TradingDB_full.bak'
  WITH NORECOVERY, REPLACE, STATS=5;

为什么要用 SMB Direct?

因为 TB 级的库用传统 TCP 走管理/业务网络,CPU 与瓶颈会很明显;RDMA 的 SMB 能把这段“迁移/播种”时间缩到极短,并且不和交易侧 TCP 冲突。

3. 创建 AG(HKSQL1 主,HKSQL2 同步自动切换,HKSQL3 异步只读)

-- 在主副本(HKSQL1)上
CREATE AVAILABILITY GROUP [AG_Trading]
WITH (DB_FAILOVER = ON, CLUSTER_TYPE = WSFC, AUTOMATED_BACKUP_PREFERENCE = SECONDARY)
FOR DATABASE [TradingDB]
REPLICA ON
N'HKSQL1' WITH (
    ENDPOINT_URL = 'TCP://hksql1.corp.local:5022',
    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
    FAILOVER_MODE = AUTOMATIC,
    SEEDING_MODE = MANUAL,            -- 我们已用 SMB 预播种;也可改 AUTOMATIC
    SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)
),
N'HKSQL2' WITH (
    ENDPOINT_URL = 'TCP://hksql2.corp.local:5022',
    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
    FAILOVER_MODE = AUTOMATIC,
    SEEDING_MODE = MANUAL,
    SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)
),
N'HKSQL3' WITH (
    ENDPOINT_URL = 'TCP://hksql3.corp.local:5022',
    AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT,
    FAILOVER_MODE = MANUAL,
    SEEDING_MODE = MANUAL,
    SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)
);
GO

在 HKSQL2/3 上加入 AG:

ALTER AVAILABILITY GROUP [AG_Trading] JOIN;
ALTER DATABASE [TradingDB] SET HADR AVAILABILITY GROUP = [AG_Trading];
GO

创建 Listener(客户端网络):

ALTER AVAILABILITY GROUP [AG_Trading]
ADD LISTENER N'AG-TRADING'
( WITH IP ((N'10.10.10.50', N'255.255.255.0')), PORT=1433 );
GO

提交模式选择:

  • HKSQL1↔HKSQL2:SYNCHRONOUS_COMMIT + AUTOMATIC FAILOVER(同机柜、低 RTT)
  • HKSQL3:ASYNCHRONOUS_COMMIT(远端/只读,避免影响主事务提交)

步骤四:性能验证与关键指标

监控(上线前必须盯的计数器)

AG 复制通道

  • SQLServer:Database Replica\Log Send Queue KB(主)
  • SQLServer:Database Replica\Redo Queue KB(从)
  • SQLServer:Availability Replica\Flow Control\*

事务与等待

  • SQLServer:SQL Statistics\Batch Requests/sec
  • sys.dm_os_wait_stats 中 HADR_SYNC_COMMIT、WRITELOG

SMB Direct

  • \SMB Direct Connection(*)\Throughput
  • Get-SmbMultichannelConnection(Rdma=True,通道数量、LinkSpeed)

IO

  • sys.dm_io_virtual_file_stats(写延迟 ms/IO)
  • 磁盘队列长度、NVMe 驱动延迟

网络

  • 交换机端口 PFC 统计(优先级 3 的 pause 帧计数不应持续攀升)

我们那夜的对比数据(节选)

指标 优化前(无 RDMA/SMB Direct,播种走 TCP) 优化后(RDMA + SMB Direct + QoS)
首播种 1.2TB 耗时 3 小时 40 分 54 分钟
早盘峰值 P99 事务提交(ms) 7.3 4.1
Log Send Queue KB(峰值) 220,000+ < 80,000
Redo Queue KB(峰值) 150,000+ ~ 50,000
SQL 进程 CPU(播种期) 60–70% 25–35%
SMB 链路实际吞吐(单向) ~ 6–8 Gbps 21–23 Gbps(25G ×1 通道)

交易高峰时,提交路径主要受 WRITELOG 与存储/日志盘影响。RDMA 并不会魔法般降低 WRITELOG,但通过释放网络与 CPU 抢占、加速播种/备份窗口、稳定副本队列,让系统在峰值更“稳态”,这就是我们观测到 P99 的改善来源。

步骤五:运营级别的细节优化(能救命的小技巧)

  • 把 SMB/备份从业务网络“搬家”到 RDMA 平面:避免和客户端连接、AG TCP 竞争队列。
  • 固定路由与 DNS 解析:SMB 指向 SOFS 的 A 记录只在 RDMA VLAN 可达;必要时用 New-SmbMultichannelConstraint 限制接口。
  • Listener 只落在客户端网络:避免客户端“聪明”地往 RDMA 去连。
  • NVMe 日志盘:保证 WRITELOG 的物理下限;把写入队列长度控制在稳定区间。
  • 自动备份偏好:在 AG 上设置 AUTOMATED_BACKUP_PREFERENCE = SECONDARY,二副本承担备份,备份文件经 RDMA 出去,不打扰主库。
  • 压测工具:HammerDB/TPC-E/TPC-C 自建脚本,尤其关注写密集混合负载下的 WRITELOG、HADR_SYNC_COMMIT 等等待类型。

现场踩坑与排障手记(真实发生)

坑 1:看起来 RDMA 了,实际上没有

症状:Get-SmbMultichannelConnection 里 Rdma=False,吞吐与 CPU 占用像普通 TCP。

排法:

  • 查交换机与服务器 PFC/ETS/MTU 是否一致;
  • Windows 端是否 约束到 RDMA 接口;
  • Mellanox 驱动:确认 RoCE v2;
  • Get-SmbClientNetworkInterface:RDMA Capable 必须为 True。

解决:发现交换机端某条上联口没开 PFC,补上后立刻 Rdma=True,吞吐爬升。

坑 2:PFC 暂停风暴

症状:RDMA 突然掉速、AG 复制延迟爬升、交换机队列不稳定。

原因:某台存储节点的微突发把整条优先级 3 拖住了。

解决:

  • 把 ETS 的带宽分配更细(50–60% 给 SMB,留足其它队列);
  • 在脊交换开启 ECN;
  • 分散热点(SOFS 的 CSV 亲和、RDMA 通道数调整)。

坑 3:AG 创建后,端点连不上

症状:The server network address "TCP://..." cannot be reached...

排法:

  • 防火墙是否放行 5022;
  • 端点是否 STATE=STARTED;
  • 端点身份验证是否使用域服务账号(避免证书错配);
  • DNS 是否解析到业务网而不是 RDMA 网。

解决:清理旧证书配置,全部改为域服务账号,立刻恢复。

坑 4:Jumbo 配半截

症状:一端 9014,另一端 1500,吞吐上不去且有间歇性重传。

解决:端到端统一,链路所有口都验证 MTU,包括 LACP 成员。

坑 5:SMB 不走 RDMA 而走了管理口

症状:SOFS 的 A 记录在管理 VLAN 先被命中。

解决:给 SMB 访问显式指定 短名或 RDMA VLAN 的专用记录,并用 New-SmbMultichannelConstraint 钉死接口。

变更与回退策略(线上友好)

  • 分阶段启用:先在 SOFS 与一台 SQL 之间开启 RDMA,验证无误后再扩到全体;
  • DCB/ETS 变更窗口:先在链路下游(服务器端口)开,确认不误伤,再到上游(叶/脊);
  • AG 只读副本先改造:把备份/只读流量先搬到 RDMA,主库不动;
  • 回退路径:保留 TCP 访问共享的路径与策略,Remove-SmbMultichannelConstraint 即可回退。

运维清单(可复用)

  •  BIOS/固件/驱动统一到验证版本
  •  交换机全链路 MTU 9216
  •  服务器 NIC Jumbo 9014
  •  PFC on 3、ETS ≥ 50% 给 SMB
  •  Enable-NetAdapterRdma + Get-SmbMultichannelConnection 验证 Rdma=True
  •  SOFS 共享权限给 SQL 服务账号
  •  AG:主-从同步提交 + 自动切换;只读异步副本
  •  备份偏好 Secondary;备份/播种走 \\sofs\...
  •  PerfMon 模板导入:HADR/SMB/IO/CPU/Network
  •  回退与变更记录归档

FAQ:几个常见误解

“RDMA 会让 AG 复制更快吗?”
不会直接。AG 复制是 TCP 端点。但 RDMA 能把与 AG 并行的大流量 SMB从业务网络剥离出去,降低 CPU 与队列竞争,间接让系统更稳,从而改善高分位延迟。

“要不要 iWARP?”
RoCEv2 在数据中心更常见;iWARP 不需要 PFC,运维更简单。若你无法统一好 PFC/ETS,且有 iWARP NIC 资源,iWARP 也能是务实选择。

“Jumbo 一定有用吗?”
对大流量 SMB 有益,但必须端到端一致。否则弊大于利。

附:常用命令与脚本片段(收藏级)

PowerShell:一键校验 RDMA + SMB Direct

$server="sofs.corp.local"
Test-Connection $server -Count 2 | Out-Null

Write-Host "=== NIC & RDMA ==="
Get-NetAdapterRdma | ft Name,Enabled
Get-SmbClientNetworkInterface | ft InterfaceIndex,RdmaCapable,RssCapable,LinkSpeed

Write-Host "=== SMB MultiChannel ==="
($c = Get-SmbMultichannelConnection | where {$_.ServerName -eq $server})
$c | ft ServerName,ClientInterfaceIndex,Rdma,State,NumOfConnections

if($c -and ($c.Rdma -contains $true)) { "RDMA OK" } else { "RDMA NOT IN USE" }

T-SQL:关键 DMV 观察

-- HADR 队列
SELECT
  ar.replica_server_name,
  drs.database_id,
  drs.log_send_queue_size,      -- KB
  drs.redo_queue_size,          -- KB
  drs.synchronization_state_desc,
  drs.synchronization_health_desc
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id;

-- 写日志等待与 top waits
SELECT TOP 10 wait_type, wait_time_ms, 100.0 * wait_time_ms / SUM(wait_time_ms) OVER() AS pct
FROM sys.dm_os_wait_stats
ORDER BY wait_time_ms DESC;

早上 8:59,开盘前一分钟,监控墙上的 P99 线条像被人按住了头。交易开始后,AG 的 Log Send Queue 有起伏,但很快被压平;WRITELOG 的尖峰低了,SMB 通道吞吐稳定在 20Gbps 出头,SQL 进程 CPU 也没再飙。
走出机房时,外面开始热闹起来。那晚我们没动业务 SQL 一行代码,只是把流量与通道分好了层级,让该走 RDMA 的走 RDMA,让 AG 的 TCP 少受打扰。
做系统,很多时候不是“更快”,而是“更稳更可预期”。如果你也在香港的机房里和延迟较劲,希望这份记录能帮你把那条线按下去。

TL;DR(复刻步骤清单)

  • 硬件就位:RDMA NIC(RoCEv2)、交换机开 DCB(PFC/ETS)、NVMe 日志盘;
  • Windows:Enable-NetAdapterRdma、巨帧、New-NetQosPolicy(优先级 3)、New-NetQosTrafficClass、Enable/Disable-NetQosFlowControl;
  • SOFS:S2D + 共享(备份/播种),权限给 SQL 服务账号;
  • SMB Direct 验证:Get-SmbMultichannelConnection Rdma=True;
  • AG:主/同步副本自动切换,异步只读副本;Listener 在客户端网;
  • 备份/播种走 RDMA,业务走客户端网,路径隔离;
  • 压测与监控:HADR 队列、SMB 吞吐、WRITELOG 等;
  • 处理坑:PFC 风暴、Jumbo 不一致、端点/防火墙、DNS 接口绑错。
目录结构
全文