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

如何在香港服务器上通过Windows Failover Cluster配置SQL Server AlwaysOn,实现高可用数据库架构?

发布人:Minchunlin 发布时间:2025-08-26 10:21 阅读量:802


第一次去香港 MEGA 机房接这套库的时候,是个周五凌晨 1 点。冷通道风像刀子一样,我把手伸进机柜理网线时,耳边只有风扇的嘶嘶声和 KVM 小屏上“Press any key to continue”的跳动。运营同学在门口补充登记,我这边把两台主机的 iDRAC/IPMI 接好、贴好资产标签,拨通运维群里的语音,开始执行我们的计划:在同城机房内搭一套 Windows Server Failover Cluster(WSFC),承载 SQL Server AlwaysOn 可用性组,做到 RPO≈0、RTO<30s 的高可用。

那杯打开就忘在机柜顶上的咖啡,等我想起来,已经是切换演练结束之后了。

目标与边界

架构目标:同城双节点 + 文件共享见证(File Share Witness)的 WSFC,承载 SQL Server AlwaysOn 可用性组(多数据库,同步提交,自动故障转移),对外用 Listener 暴露一个固定服务名。

业务目标:主备实时同步、备库可读(报表/只读查询),计划内切换<10s,计划外自动切换<30s。

约束与选择:

  • Windows Server 2022 Datacenter(包含 WSFC)
  • SQL Server 2019/2022 Enterprise(AlwaysOn 完整特性;如果是 Standard 只能用 Basic AG,功能限制较多)
  • 域环境使用 Active Directory(生产推荐;工作组模式也能做,但维护与排障成本更高)
  • 同一机房同一子网(单子网 Listener,收敛复杂度)

硬件与网络清单(实际参数)

角色 型号/CPU 内存 系统盘 数据盘 网卡 OS / SQL
HK-SQL01 Dell R7525 / AMD EPYC 7313P 256 GB 2×480 GB SATA SSD (RAID1) 4×1.92 TB NVMe(Data/Log/TempDB 分盘) 2×10GbE(Bond/Team) + 1×1GbE 管理 Win Server 2022 Datacenter / SQL Server 2019 Ent CU 现行
HK-SQL02 同上 256 GB 同上 同上 同上 同上
HK-DC01(域控+见证) 轻配 64 GB 2×480 GB 2×1 TB SSD 2×1GbE Win Server 2022 / AD DS

机房网络:单子网 10.10.20.0/24;管理网(Out-of-band)独立;到广州骨干 < 20ms(测得 16–18ms),同子网内 0.2–0.3ms。

IP 规划

名称 IP 备注
HK-SQL01 10.10.20.11 生产网
HK-SQL02 10.10.20.12 生产网
HK-DC01 10.10.20.10 域控 + 文件共享见证
HK-DB-CL1(集群名) 10.10.20.40 WSFC VIP
AGLISTENER(AG 监听器) 10.10.20.50 SQL 客户端连接入口

端口白名单(防火墙/ACL 必开)

组件 端口 用途
WSFC 3343/UDP 心跳
RPC/Cluster 135/TCP + 49152-65535/TCP 集群/远程管理
SMB 445/TCP 文件共享见证
SQL 1433/TCP 客户端连接
HADR Endpoint 5022/TCP 可用性组数据通道

系统准备与基线优化

1)固件与 BIOS

BIOS 调整为 Performance(禁 C-States),内存 profile 固定,确保延迟与抖动最小。

NVMe 开启命名空间对齐;控制器固件更新到机房白名单版本。

2)Windows 基线

# 功能安装(含WSFC)
Install-WindowsFeature Failover-Clustering, RSAT-AD-PowerShell -IncludeManagementTools

# 时钟同步,域控为权威时钟(也可配置独立NTP)
w32tm /config /manualpeerlist:"time.windows.com,0x8" /syncfromflags:manual /reliable:yes /update
w32tm /resync

3)磁盘与文件系统

数据盘、日志盘、TempDB 物理分离,64K 分配单元,禁用压缩。

Get-Disk | Where PartitionStyle -Eq 'RAW' | Initialize-Disk -PartitionStyle GPT
New-Partition -DiskNumber 3 -DriveLetter D -UseMaximumSize | Format-Volume -FileSystem NTFS -AllocationUnitSize 65536 -NewFileSystemLabel "DATA"
New-Partition -DiskNumber 4 -DriveLetter L -UseMaximumSize | Format-Volume -FileSystem NTFS -AllocationUnitSize 65536 -NewFileSystemLabel "LOG"
New-Partition -DiskNumber 5 -DriveLetter T -UseMaximumSize | Format-Volume -FileSystem NTFS -AllocationUnitSize 65536 -NewFileSystemLabel "TEMPDB"

4)SQL Server 安装与补丁

使用域服务账号 HKDOM\sqlsvc 作为 SQL 服务账户(最小权限,非管理员)。

安装后立即打到当前 CU。

基线参数:

-- 最大内存(预留 OS 与备端工具),按256G主机预留 ~32G
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'max server memory (MB)', 215040; RECONFIGURE;

-- MAXDOP:按NUMA和核心布局(EPYC 7313P 16c,单路),OLTP 取 8
EXEC sp_configure 'max degree of parallelism', 8; RECONFIGURE;

-- TempDB:8~12 个数据文件,等大小,独立盘 T:\

搭建域与文件共享见证

在 HK-DC01 上部署 AD DS,建域 hkdom.local,把两台 SQL 节点加域。

创建文件共享 \\HK-DC01\WSFCWitness,仅集群计算机对象 HK-DB-CL1$ 与节点计算机对象有 读写。

创建 Windows Failover Cluster(WSFC)

1)节点验证(必须做,失败别硬上)

Test-Cluster -Node HK-SQL01,HK-SQL02 -Include "Storage","Inventory","Network","System Configuration"

常见报错:网络多路径命名不一致、心跳网络被打上公用标记等;按报表修即可。

2)创建集群

New-Cluster -Name "HK-DB-CL1" -Node "HK-SQL01","HK-SQL02" -StaticAddress "10.10.20.40" -NoStorage

3)设置仲裁(文件共享见证)

Set-ClusterQuorum -Cluster "HK-DB-CL1" -NodeAndFileShareMajority "\\HK-DC01\WSFCWitness"

4)可选:心跳阈值(同子网通常默认就好)

(Get-Cluster).SameSubnetDelay = 1000     # ms
(Get-Cluster).SameSubnetThreshold = 5    # 次

启用 AlwaysOn 与 HADR Endpoint

1)启用 AlwaysOn(两节点都要)

在“SQL Server 配置管理器”里勾选“可用性组”,或用注册表/PowerShell。启用后重启 SQL 服务。

2)创建 HADR Endpoint(端口 5022)

采用 Windows 身份验证,授予服务账号连接权限。

-- 两个节点都执行
CREATE ENDPOINT [Hadr_endpoint]
    STATE = STARTED
    AS TCP (LISTENER_PORT = 5022)
    FOR DATA_MIRRORING (ROLE = ALL, ENCRYPTION = REQUIRED, ALGORITHM = AES);

-- 在每个实例授予服务账号连接端点权限
CREATE LOGIN [HKDOM\sqlsvc] FROM WINDOWS;
GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [HKDOM\sqlsvc];

3)准备数据库

主库做一次 FULL + LOG 备份;检查数据库为 FULL 恢复模式。

确保两端 排序规则一致、兼容级别一致。

创建可用性组(两种方式:自动播种 vs 传统备份还原)

方案 A:自动播种(推荐,干净、快)

在主库(HK-SQL01)执行:

-- 1) 创建 AG(自动播种,自动故障转移,同步提交,可读次要)
CREATE AVAILABILITY GROUP [AG_HK_CORE]
WITH (AUTOMATED_BACKUP_PREFERENCE = SECONDARY, DB_FAILOVER = ON, SEEDING_MODE = AUTOMATIC)
FOR REPLICA ON
N'HK-SQL01' WITH (
    ENDPOINT_URL = N'TCP://HK-SQL01.hkdom.local:5022',
    FAILOVER_MODE = AUTOMATIC,
    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
    BACKUP_PRIORITY = 60,
    SECONDARY_ROLE(ALLOW_CONNECTIONS = READ_ONLY)),
N'HK-SQL02' WITH (
    ENDPOINT_URL = N'TCP://HK-SQL02.hkdom.local:5022',
    FAILOVER_MODE = AUTOMATIC,
    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
    BACKUP_PRIORITY = 50,
    SECONDARY_ROLE(ALLOW_CONNECTIONS = READ_ONLY));
GO

-- 2) 将数据库加入 AG(自动播种会在备端自动创建)
ALTER AVAILABILITY GROUP [AG_HK_CORE] ADD DATABASE [CoreDB], [CRMDB];
GO

在备库(HK-SQL02)执行:

ALTER AVAILABILITY GROUP [AG_HK_CORE] JOIN;
GO
ALTER DATABASE [CoreDB] SET HADR AVAILABILITY GROUP = [AG_HK_CORE];
ALTER DATABASE [CRMDB] SET HADR AVAILABILITY GROUP = [AG_HK_CORE];

注意:自动播种要求两端有足够权限写 MDF/LDF,磁盘路径需一致或确保 SQL 能创建目录。

方案 B:传统备份/还原(在高带宽不稳定时更踏实)

主库:

BACKUP DATABASE [CoreDB] TO DISK='\\HK-SQL01\backup\CoreDB_full.bak' WITH COPY_ONLY, COMPRESSION;
BACKUP LOG [CoreDB] TO DISK='\\HK-SQL01\backup\CoreDB_log.trn' WITH COMPRESSION;

备库(NORECOVERY 还原):

RESTORE DATABASE [CoreDB] FROM DISK='\\HK-SQL01\backup\CoreDB_full.bak' WITH NORECOVERY, REPLACE;
RESTORE LOG [CoreDB] FROM DISK='\\HK-SQL01\backup\CoreDB_log.trn' WITH NORECOVERY;

加入 AG:

ALTER AVAILABILITY GROUP [AG_HK_CORE] JOIN;
ALTER DATABASE [CoreDB] SET HADR AVAILABILITY GROUP = [AG_HK_CORE];

创建 Listener(客户端的唯一入口)

单子网场景(本次部署):

ALTER AVAILABILITY GROUP [AG_HK_CORE]
ADD LISTENER N'AGLISTENER' (
    WITH IP ((N'10.10.20.50', N'255.255.255.0')),
    PORT=1433);

 

SPN(确保 Kerberos,减少双跳问题)

在域控上(或有 RSAT 的终端):

setspn -S MSSQLSvc/AGLISTENER.hkdom.local:1433 HKDOM\sqlsvc
setspn -S MSSQLSvc/AGLISTENER:1433 HKDOM\sqlsvc

客户端连接串(.NET/ODBC)

Server=AGLISTENER.hkdom.local;Database=CoreDB;Integrated Security=True;MultiSubnetFailover=True;ApplicationIntent=ReadOnly

单子网也建议 MultiSubnetFailover=True,驱动会优化连接握手;只读流量可通过 ApplicationIntent=ReadOnly 自动打到可读副本。

备份与维护(尊重 AG 偏好)

备份偏好:在 AG 层设置 “Prefer Secondary”。作业里调用函数判断本机是否应执行。

作业脚本示例(通用全/差/日志,自动判断)

IF sys.fn_hadr_backup_is_preferred_replica(DB_NAME()) = 1
BEGIN
    DECLARE @dt nvarchar(20)=CONVERT(nvarchar(20),GETDATE(),112)+'_'+REPLACE(CONVERT(nvarchar(8),GETDATE(),108),':','');
    BACKUP DATABASE [CoreDB] TO DISK = N'\\backupshare\CoreDB_FULL_'+@dt+'.bak' WITH COPY_ONLY, COMPRESSION, CHECKSUM;
END

同理加差异与日志备份作业。二次校验 msdb.dbo.backupset,并用 RESTORE VERIFYONLY。

维护与作业漂移:

  • 需要在两端都创建相同的 SQL Agent 作业,但靠脚本判断是否执行。
  • 索引/统计维护尽量在主副本(避免同步带来的额外日志量),并选择业务低峰。

监控与告警

关键 DMV 查询

-- 同步健康与延迟
SELECT ag.name, ar.replica_server_name, drs.synchronization_state_desc, drs.log_send_queue_size, drs.redo_queue_size, drs.end_of_log_lsn, drs.redo_rate
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_replicas ar ON drs.replica_id=ar.replica_id
JOIN sys.availability_groups ag ON ar.group_id=ag.group_id;

-- 会话状态与可读二级副本连接数
SELECT * FROM sys.dm_hadr_availability_replica_states;

集群日志(排障利器)

Get-ClusterLog -UseLocalTime -Destination C:\ClusterLogs -TimeSpan 5

性能计数器:SQLServer:Availability Replica / Database Replica;物理磁盘延迟;网络吞吐与重传。

切换演练(计划内 & 计划外)

计划内切换(零丢失)

在当前主库(HK-SQL01):

ALTER AVAILABILITY GROUP [AG_HK_CORE] FAILOVER;

预期:几秒内 Listener 指向 HK-SQL02,业务短暂抖动,连接自动重连。

计划外强制切换(允许丢失)

仅灾难演练用,确保业务明确知情:

ALTER AVAILABILITY GROUP [AG_HK_CORE] FORCE_FAILOVER_ALLOW_DATA_LOSS;

我们真实踩过的坑 & 现场修复

端点 5022 被防火墙拦截

现象:AG 加入卡住,The connection to the primary replica is not active。

解决:Windows 防火墙入站规则显式放行 5022/TCP,机房 ACL 同步开白。

排查技巧:Test-NetConnection HK-SQL02 -Port 5022。

SPN 缺失导致 Kerberos 降级为 NTLM

现象:连接延迟偶发飙高(特别是 AD 压力大时)。

解决:为 Listener 绑定 MSSQLSvc/AGLISTENER... 到服务账号,并清理重复 SPN;klist purge 刷票测试。

自动播种失败(磁盘路径不存在)

现象:AG 里的 DB 状态 NOT_SYNCHRONIZING,错误里有 Operating system error 3(The system cannot find the path specified.)。

解决:在备端预创建目录结构(例如 D:\MSSQL\Data / L:\MSSQL\Log / T:\TempDB),重试播种。

WSFC 验证报告网络告警

现象:Validate Network Communication 黄色告警,标记了多网卡。

解决:在 Failover Cluster Manager → Networks 中把管理/带外网卡标记为 Do not allow cluster network communication。

备库只读负载把 REDO 压趴

现象:报表在副本跑得猛,redo_queue_size 飙升,同步延迟上升。

调整:给副本加内存保留,控制报表并发;必要时把报表迁到延时副本或额外只读副本(异步)。

TempDB 没分盘导致日志同步被拖累

现象:日志刷盘等于总盘延迟,AG 同步队列飙升。

解决:TempDB 独占 NVMe,预分配文件、固定增长(避免频繁扩展)。

跨域名解析偶发抖动

现象:客户端偶发解析到旧 IP。

解决:确保 Listener 的 DNS TTL 合理(默认 120s 可调),并在关键应用侧启用连接重试策略。

验收与指标(我们上线当晚的真实数据)

指标
计划内切换(主→备) 6–8s(应用自动重连,平均 6.4s)
计划外断电演练(主节点失联) 20–25s 自动故障转移(含检测阈值)
同步延迟(业务低峰) < 5ms,log_send_queue_size≈0
只读副本吞吐(报表) 峰值 ~ 18k Batch Requests/sec
数据盘延迟(P99) 1.2–1.8ms(NVMe)

运维清单(上线之后每天/每周要做的事)

每天:巡检 DMV、SQL Agent 作业执行、备份可恢复性抽检(RESTORE VERIFYONLY)。

每周:下载并归档 ClusterLog、Windows 事件日志;只读副本压力测试,确认不会影响 REDO。

每月:打补丁窗口(先备后主,滚动升级),AG 切换演练一次;容量与增长评估。

突发:监控告警(同步队列、心跳抖动、磁盘 P99),第一时间抓取现场信息。

附:端到端部署流程速查(可当 Runbook)

  1. 机房上架 → 布线 → iDRAC → 固件/BIOS 基线
  2. 安装 Windows 2022 → 打补丁 → 加域
  3. 盘符规划(D/L/T)→ NTFS 64K → SQL 安装(域服务账号)→ CU
  4. DC 上创建文件共享见证
  5. 节点跑 Test-Cluster → New-Cluster → Set-ClusterQuorum
  6. SQL 启用 AlwaysOn → 创建 HADR Endpoint(5022)
  7. 选自动播种或备份/还原 → 创建/加入 AG
  8. 创建 Listener(10.10.20.50:1433)→ 配置 SPN
  9. 放通端口/防火墙 → 客户端连通测试(MultiSubnetFailover=True)
  10. 备份&维护作业部署(尊重 AG 偏好)→ 监控上报
  11. 计划内/计划外切换演练 → 验收指标归档

结尾:3 点 17 分,我把那杯凉咖啡一口闷了

切完最后一次计划外演练时已经 3 点多。我看着监控面板上的绿色,redo_queue_size 归零,Listener 的连接数平稳落回主库。机柜门关上的一瞬间,冷通道的风声也像安静了下来。
我端起那杯已经凉透的咖啡,一口闷了,然后在微信群里发了上线确认:“香港库 AlwaysOn 高可用上线,RPO≈0、RTO<30s,演练通过。”
这套方案不是最华丽的,但它在真实的机房、真实的链路、真实的流量下跑得稳。这就是我们做运维想要的——一套能扛事、能落地、能复用的高可用架构。

可复制的配置片段(集中放一处,拿就能用)

PowerShell:WSFC

Install-WindowsFeature Failover-Clustering -IncludeManagementTools
Test-Cluster -Node HK-SQL01,HK-SQL02
New-Cluster -Name "HK-DB-CL1" -Node "HK-SQL01","HK-SQL02" -StaticAddress "10.10.20.40" -NoStorage
Set-ClusterQuorum -NodeAndFileShareMajority "\\HK-DC01\WSFCWitness"

T-SQL:HADR Endpoint + AG(自动播种)

CREATE ENDPOINT [Hadr_endpoint]
    STATE = STARTED
    AS TCP (LISTENER_PORT = 5022)
    FOR DATA_MIRRORING (ROLE = ALL, ENCRYPTION = REQUIRED, ALGORITHM = AES);

CREATE LOGIN [HKDOM\sqlsvc] FROM WINDOWS;
GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [HKDOM\sqlsvc];

CREATE AVAILABILITY GROUP [AG_HK_CORE]
WITH (AUTOMATED_BACKUP_PREFERENCE = SECONDARY, DB_FAILOVER = ON, SEEDING_MODE = AUTOMATIC)
FOR REPLICA ON
N'HK-SQL01' WITH (ENDPOINT_URL=N'TCP://HK-SQL01.hkdom.local:5022', FAILOVER_MODE=AUTOMATIC, AVAILABILITY_MODE=SYNCHRONOUS_COMMIT, SECONDARY_ROLE(ALLOW_CONNECTIONS=READ_ONLY)),
N'HK-SQL02' WITH (ENDPOINT_URL=N'TCP://HK-SQL02.hkdom.local:5022', FAILOVER_MODE=AUTOMATIC, AVAILABILITY_MODE=SYNCHRONOUS_COMMIT, SECONDARY_ROLE(ALLOW_CONNECTIONS=READ_ONLY));

ALTER AVAILABILITY GROUP [AG_HK_CORE] ADD DATABASE [CoreDB], [CRMDB];

T-SQL:Listener

ALTER AVAILABILITY GROUP [AG_HK_CORE]
ADD LISTENER N'AGLISTENER' (WITH IP ((N'10.10.20.50', N'255.255.255.0')), PORT=1433);

Kerberos SPN

setspn -S MSSQLSvc/AGLISTENER.hkdom.local:1433 HKDOM\sqlsvc
setspn -S MSSQLSvc/AGLISTENER:1433 HKDOM\sqlsvc

连接串

Server=AGLISTENER.hkdom.local;Database=CoreDB;Integrated Security=True;MultiSubnetFailover=True;ApplicationIntent=ReadOnly

如果你也要在香港机房落地这套架构,把上面的 Runbook 按顺序做一遍,再结合“坑与修复”的清单,基本就能一次过。若你的环境是多子网/跨机房、多副本、或要做混合云延伸,我们也可以在这个基线之上扩展(MultiSubnet Listener、异步 DR 副本、Azure Cloud Witness 等),但那又是另一个凌晨、另一个故事了。

目录结构
全文