news 2026/10/23 12:01:49

SQL Server Always On高可用架构自建实战:从云RDS迁移到物理机的成本与运维全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQL Server Always On高可用架构自建实战:从云RDS迁移到物理机的成本与运维全解析

SQL Server 在云上的账单,很多团队是到了月底看费用报表才吓一跳的。我接手的时候,公司核心业务库跑在一朵公有云的托管实例上,16 vCPU 64 GB 内存,标准版按量付费,算上存储、备份和公网流量,一个月稳定在两万八左右。这不是最离谱的,最离谱的是每年续费谈判基本没有余地,RDS 实例的规格就像套餐,想升配置,价格跳档更狠。当时财务找我核对成本,说这个数据库一年的开销快顶三个新员工的工资了,我翻了翻账单,确实,一年下来接近三十四万。

后来我花了大概两周时间,把核心库从云 RDS 迁到了自己买的物理服务器上,用 SQL Server Always On 可用性组做了双副本高可用。数据迁移完成之后,云上那台实例直接退掉,第二年算总账,数据库软硬件和运维成本大概七万出头,含服务器折旧、windows 授权分摊、备份存储,省下来的额度刚好覆盖公司两三个月的云资源预算。这篇文章我不写广告,也不吹“自建无敌”,就把我实际的选型逻辑、搭建步骤、故障转移测试和踩过的坑全部摊开讲,希望能给正在纠结要不要自建 SQL Server 高可用架构的同学一个真实参考。

1. 为什么一个高可用数据库要花掉一年三十多万

1.1 云数据库账单到底贵在哪里

先说清楚,云 RDS 本身不坑,坑的是 SQL Server 的许可模型叠加到云基础设施之后,费用变得非常不透明。拿我们之前用的那台 16C64G 标准版实例来说,计费项大致是:

  • 实例规格:按 vCPU 和内存计费,标准版 SQL Server 在云上并不是单纯卖资源,它把微软的许可证成本打包进每小时价格里,所以你会看到同等规格下 SQL Server 实例比 MySQL 实例贵出一大截。
  • 存储空间:SSD 云盘按 GB 计费,我们核心库加日志文件接近 700 GB,每月存储费用是大头之一。
  • 备份存储:RDS 默认保留 7 天全量备份,这部分超出免费额度之后按容量收费,数据库变更频繁的话,备份集膨胀速度比想象中快很多。
  • 公网流量:即便内部系统走内网,总有几个外部渠道要连数据库,流量费积少成多。

单个看都不算离谱,叠在一起就吓人了。最让我不舒服的是,无论你的业务凌晨是不是空闲,那台实例的每小时费用都在跑,全年 8760 小时一分不少。而 SQL Server 的 Always On 可用性组天生就是一对多的日志流转架构,主库一个事务提交,日志块就推给副本,这种复制机制对云平台而言并不稀缺,但云厂商把它包装成“高可用版”之后,价格直接再上一个台阶。

1.2 换算一下自建方案的账

我当时算了这么一笔账:

  • 两台物理机,双路 8 核 64 GB 配置,整机采购加三年质保,单台三万二,两台合计六万四。
  • 微软 SQL Server 标准版许可,按两核一授权购买,16 核需要 8 个授权,我们走的是公司已有的软件资产协议,分摊到本项目约两万三。
  • Windows Server 数据中心版授权,自带两个虚拟化实例权限,刚好覆盖两台宿主机,费用约一万二。
  • 备份盘用 NAS 加冷备硬盘,三万左右。
  • 交换机、网线、机柜、UPS 这些零碎,摊到一年里几乎可以忽略。

全部投入一次性约十二万九,按三年折旧算,平摊到每年四万三,再加机房电费和维护人力折算,年化也就六到七万。相比云 RDS 一年三十四万的账单,省下来的不只是钱,还有预算审批的周期。当然,物理服务器不是唯一的选择,我们后面聊的 Always On 架构,也可以全部跑在公司已有的虚拟化集群里,成本会进一步压低,只是性能隔离要稍微多花点心思。

1.3 为什么非要用 Always On,而不是日志传送或镜像

很多 DBA 会问,SQL Server 高可用方案又不是只有 Always On,日志传送、数据库镜像、复制都能用,为什么偏偏选它。我的理由很实际:

  • 日志传送的备库处于 Restoring 状态,不能读,故障切换时要手动恢复所有日志,RPO 做不到很干净。
  • 数据库镜像在 SQL Server 2012 之后基本进入维护模式,虽然能用,但微软自己都在推 Always On 了,没必要给未来的坑买单。
  • Always On 可用性组把多个数据库作为一个组管理,主库和副本之间实时同步日志,副本处于在线状态,不仅可以做只读查询,还能在计划内切换时把业务中断时间压到秒级。

我们用 Always On,最看重的其实是“读扩展”这个附带能力。报表查询、统计任务以前全挤在主库上,经常半夜把锁争用拉高,做成分组副本之后,只读请求全部路由到副库,主库的负载肉眼可见地降了一截。

2. 动手之前必须吃透的 Always On 原理和取舍点

2.1 可用性组本质上是日志流的接力赛

Always On 的核心机制可以理解成一本账本:主库每发生一个事务,就写一条日志记录,然后这些日志记录会被“快递”到每个副本,副本收到之后不停重放,让自身的数据和主库保持同步。和复制订阅不同,Always On 复制的是日志记录本身,不是数据行,所以它对业务表的 schema 变更几乎无感,DDL 操作也会正常同步过去。

数据库加入可用性组后,主库上每个事务提交前,日志块就已经发送到副本。这里有两个关键动作:

  • 主库把日志块写入本地日志文件。
  • 日志发送队列把日志块推给每个副本的接收线程。

副本端拿到日志后写入自己的日志文件,再通过重做线程应用到数据文件。整个过程是异步并行管道,性能损耗通常控制在 2% 到 5% 之间,但如果网络质量差或者磁盘延迟高,日志发送队列会积压,主库也会受到影响。

2.2 同步提交和异步提交不是“快慢”问题,是命悬一线的取舍

Always On 有两种可用性模式:

  • 同步提交模式:主库必须等到副本确认日志已经落盘,事务才算提交成功。这样任何一台机器突然断电,数据也不会丢,代价是每次提交多一次网络往返。
  • 异步提交模式:主库不管副本收没收到,自己提交成功就返回,性能好,但真遇到主库瞬间崩溃,副本可能少掉最后几秒的事务。

我们业务是订单、支付、库存这类核心数据,坚决不能丢,所以主副本全部设成同步提交。同步模式下,我实测同城机房内网延迟 0.3 ms 到 0.6 ms,对业务接口的影响几乎测量不出来。如果你们是跨城市灾备场景,同步提交就会把延迟放大到几十毫秒,那就需要评估业务容忍度,通常异地副本会设成异步模式,本地副本保持同步。

2.3 两个副本加见证,还是老老实实三个副本

这是最容易想拧的地方。Always On 高可用不是说有两台机器就能自动故障转移。这里要引入一个概念叫“仲裁”:故障转移前,系统需要有一半以上的投票节点活着,才能确认谁是幸存者,避免出现两台机器都认为自己是主库的脑裂。

两个副本的情况下,整个集群只有两票,任何一台失联,投票数就剩一票,达不到多数,无法自动故障转移。解决办法是加一个文件共享见证或者云见证,作为第三票。我们用的是两台数据库服务器加一台 NAS 上的文件共享见证,四舍五入就是一个典型的“双节点加见证”拓扑。

如果你预算够,直接上三个副本更省心,因为第三副本本身有数据,既能做只读,又天然满足多数仲裁,不需要额外见证。但对我们这种成本敏感的团队,双副本加见证已经能满足 RPO 为零、RTO 在 30 秒内的要求。

2.4 可用性组和故障转移集群实例的区别

还有一个概念要区分一下:Always On 可用性组和故障转移集群实例不是一回事。故障转移集群实例是多个节点共享一套存储,无论哪台机器接管,看到的都是同一个数据库文件;可用性组是每个副本保有完整的数据副本,靠日志同步保证一致性。

用饭馆来类比:集群实例是一个厨房多套厨师团队,共用一套冰箱和灶台,厨师换了,食材不变;可用性组是每家分店都有自己的厨房和食材,总店出菜之后把菜谱同步给分店。可用性组更贴合我们对异地容灾和读扩展的需求,所以没有纠结直接选了它。

3. 环境规划和装库阶段最容易翻车的细节

3.1 服务器硬件的选型,别光看 CPU 核数

数据库服务器不是 CPU 核数越高越好,内存通道、磁盘 IO、网卡队列都会影响最终性能。我给自己的采购清单定了几条硬指标:

  • CPU 选择主频高一点的型号,数据库负载很多是单事务串行处理,高主频比多核更直接。
  • 内存至少 64 GB 起步,SQL Server 默认会吃掉大量内存做缓冲池,核心库 700 GB 数据,64 GB 内存不算宽裕。
  • 系统盘和数据盘分开,系统盘做 RAID 1,数据盘做 RAID 10,日志文件单独放一个阵列,避免日志写和随机读互相争抢。
  • 网卡要双口万兆,做网卡绑定,因为 Always On 日志同步对网络很敏感,一个网口挂了会影响整个集群健康。

物理机到位后,我先把 BIOS 里的节能模式全部关掉,CPU 频率锁定在最高档位,然后装 Windows Server,打满补丁,配置固定 IP 和 DNS。这台机器不用装桌面体验功能,我用 Server Core 模式部署,减少图形界面带来的补丁和攻击面,远程管理全部走 PowerShell。

3.2 SQL Server 安装环节的设置清单

数据库引擎装的时候有几个地方容易被默认选项带偏:

  • 服务账户不要用 Local System,我单独建了两个域账户,一个给数据库引擎服务,一个给 SQL Server Agent,权限控制在最小范围。
  • 排序规则要保持一致,两个节点安装时必须选相同的 collation,不然后面加入可用性组会报排序规则不一致的错误。
  • 实例名建议直接用默认实例,或者两边用完全一样的命名实例,避免某些应用在连接字符串里对实例名敏感。
  • 端口固定,不要用动态端口。默认实例 1433,命名实例单独固定一个端口,做防火墙策略时心里有数。

安装完成后,我给每个节点配了 max degree of parallelism 和 max server memory。MAXDOP 设成 4,避免并行查询把 CPU 打满;最大内存不要填满物理内存,留 2 到 4 GB 给操作系统。这些参数两个节点保持一致。

3.3 Windows Server 故障转移集群的搭建,顺序不能错

Always On 可用性组依赖 Windows Server 故障转移集群,所以得先把集群建起来。这一步步骤顺序千万别反,我以前见过有人先建可用性组再补集群,结果各种状态异常。

集群搭建的核心点:

  • 域环境必须正常,节点计算机加域,时间同步要配好,用 w32tm 指向同一台时间源,时间偏差超过 5 分钟,集群健康检查直接报错。
  • 创建集群时要用专门的管理账户,不能用普通域用户。
  • 集群存储验证时会检测仲裁配置,我们把文件共享见证加进去,仲裁模式设成 NodeAndFileShareMajority。

第二台节点加进来之前,先确认防火墙里开放了集群通信所需的端口:TCP 135、137、138、445,还有 RPC 动态端口范围。我在第一次搭建时因为没放行 RPC 动态端口,第二台机器一直无法加入集群,排查了快两个小时,最后用一条 netsh 命令固定了 RPC 端口范围才解决。

netsh advfirewall firewall add rule name="Cluster RPC" dir=in action=allow protocol=TCP localport=3343 netsh advfirewall firewall add rule name="Cluster RPC Dynamic" dir=in action=allow protocol=TCP localport=49152-65535

顺便提醒一下,如果公司安全策略比较严格,动态端口段会让防火墙评审很痛苦,那就干脆把 RPC 动态端口固定成一小段,比如 50000 到 50050,安全组只放行这些端口就好。

4. 配置镜像端点、创建可用性组和加入副本的完整复盘

4.1 端点权限和通信链路

集群就绪之后,要给 SQL Server 配置数据库镜像端点。Always On 的主副本和副副本之间就是通过这个端点交换日志流的。每个 SQL Server 实例默认有一个端点,名字通常叫 Hadr_endpoint,端口是 5022。

两个节点都要确保:

  • 端点的监听 IP 是节点自己的 IP,别设成 127.0.0.1。
  • 连接权限只授予两个 SQL Server 服务账户,不要给 SA 或者所有人开放。
  • 防火墙放行 5022 端口,同时确认两个节点能通过 TCP 正常访问对方的 5022。

我加完防火墙规则后习惯用 Test-NetConnection 验证一下:

Test-NetConnection 10.0.0.11 -Port 5022

返回 TcpTestSucceeded : True 再往下走,省得到时候加入副本时卡在奇怪的连接超时上。

4.2 创建可用性组和数据库副本

在主节点上,我直接用了 SSMS 的向导创建可用性组,勾选核心业务库。这一步有几个容易忽略的地方:

  • “自动故障转移”必须勾选,同时要满足两个前提:两端都是同步提交模式,并且副本健康状态检测正常。
  • “只读路由”配置先不急着填,等副本加入成功之后再补,否则向导会多出很多校验条件。
  • 数据库的全备和日志备份要用“WITH NORECOVERY”方式恢复到副本,副本数据库状态必须是 Restoring,才能作为初始数据同步的来源。

我用了一个小技巧:先把主库做一次全备,压缩后传到副本机,在副本机上手动恢复,恢复时加上 NORECOVERY。这样向导里“初始数据同步”选项就可以选“手动”,避免微软自己的种子同步机制在跨网段时慢到让人怀疑人生。

副本加入命令大概长这样:

ALTER AVAILABILITY GROUP [AGName] JOIN WITH (CLUSTER_TYPE = WSFC); GO ALTER DATABASE [CoreDB] SET HADR AVAILABILITY GROUP = [AGName]; GO

加入成功后,去仪表盘看两个副本的同步状态,正常情况下“同步状态”显示“已同步”,“故障转移就绪”显示“允许”。如果不允许,优先检查是不是某个副本还是异步模式,或者 Windows 集群健康状态有问题。

4.3 可用性组监听器,是应用无感知切换的关键

Always On 的监听器可以理解成一个虚拟网络名称,应用连接它,它会把请求转发给当前的主副本。配置监听器时需要注意:

  • 监听器名称要在域 DNS 里注册成 A 记录,公司 DNS 刷新可能不是即时生效,测试前先手动 nslookup 确认。
  • 端口要和 SQL Server 实例一致,通常就是 1433。
  • 多子网部署时勾选“启用多子网故障转移”,客户端连接字符串里也要加上 MultiSubnetFailover=True,这个是很多开发同事容易漏掉的地方。

我们应用服务器和数据库在同一网段,属于单子网,简单不少。但为了让只读请求也能分流,我在监听器下面配置了只读路由:

ALTER AVAILABILITY GROUP [AGName] MODIFY REPLICA ON 'SQL01' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=('SQL02'))); ALTER AVAILABILITY GROUP [AGName] MODIFY REPLICA ON 'SQL02' WITH (PRIMARY_ROLE(READ_ONLY_ROUTING_LIST=('SQL01')));

开发那边把报表连接的连接字符串改成:

Server=tcp:AGListener,1433;Database=CoreDB;ApplicationIntent=ReadOnly;MultiSubnetFailover=True;

加了 ApplicationIntent=ReadOnly,查询请求就会自动落到副本,不会再往主库上堆负载。

5. 故障转移演练和真实事故里的最后一公里

5.1 计划内切换必须练成肌肉记忆

高可用方案不是搭完就完事的,不练故障转移等于白搭。我每个月都会做一次计划内切换,流程固定:

  • 先用 PowerShell 挂起副本上的数据移动,做一次日志备份,确认副本日志应用没有积压。
  • 把所有写业务的连接切到维护窗口。
  • 在主节点上执行手动故障转移。
$ag = Get-ClusterResource | Where-Object {$_.Name -like "AGName*"} Move-ClusterGroup -Name $ag.Name -Node SQL02

切换的观察重点:

  • 监听器是否在 10 秒内重新上线。
  • 新的主库是不是 SQL02,副本 SQL01 是否自动进入“已同步”状态。
  • 应用连接池里的旧连接是否被正确清理。这里有个真实教训:Java 应用如果不启用连接验证,连接池会一直持有指向旧主库的死连接,故障转移后报一堆“连接已重置”错误。后来我们在连接字符串里配置了 validate 和失效检测,才算彻底解决。

5.2 无征兆断电测试测出来的问题

真正让我对这套架构有信心的是断电测试。我找机房协调,直接把主节点的电源拉掉,观察整套系统表现。

结果有几个细节很有意思:

  • Windows 集群在缺乏多数节点时会先降级,但因为文件共享见证还在,余下节点获得多数投票,完成故障转移大概花了 7 秒。
  • 主库重启后自动作为副本加回来,数据没有丢,日志流自动续传。
  • 但有一点要注意:如果断电的是机房里的核心交换机,而不是服务器本身,那节点之间完全隔离,见证又和其中一个节点在同一侧,情况就复杂了。所以有条件的话,见证最好放在第三个故障域,比如另一台 NAS 或云端主机,别和任何数据库节点放一起。

这类测试做完,建议把角色切换记录、错误日志、系统事件日志一起归档,方便后续做容量规划时回看。

5.3 日常运维监控怎么设置

自建方案最容易被诟病的就是“没人看着”。我的对策是把监控脚本化,用一个统一的监控平台收集以下指标:

  • 可用性组同步健康状态,通过 DMVsys.dm_hadr_availability_group_states拿同步状态和故障转移就绪信息。
  • 日志发送队列大小,log_send_queue_size常年大于 10000 KB 说明网络或 IO 有瓶颈。
  • 副本重做阻塞,redo_queue_size过大会导致副本延迟,影响只读查询的时效性。
  • Windows 集群事件日志里的 1135 事件,这个事件专门记录节点失联,出现一次就要查网络。

我把这些指标全部接入告警,阈值设置成:同步队列超过 20 MB 告警,持续 3 分钟;故障转移就绪状态为“否”时直接连续告警。这样即便半夜出问题,值班同事也能第一时间收到消息。

6. 省下的钱背后,还有哪些隐性成本要说清楚

6.1 自建之后真实的费用构成

项目上线三个季度后,我复盘过一次总成本。一次性硬件采购约九万四,软件授权分摊约两万三,后续每年的电费、存储介质更换、备份盘扩容加起来一万出头。一年运行成本压在六万到七万之间是可以做到的。

相比之前云 RDS 一年三十四万,确实是省了,但这个省钱的前提是公司本身有可用的物理机房、有懂 Windows 和 SQL Server 的运维人员或者 DBA,以及业务对数据库可用性有一定容忍度。

6.2 哪些情况下自建是亏的

我不能只报喜不报忧。自建方案不适合所有人:

  • 如果你的系统峰值流量波动极大,十台机器平时只用一台的算力,云数据库按量付费反而更灵活。
  • 如果你只有一个运维且同时管几十套系统,自建 SQL Server 集群会把你拖垮,高可用是要持续投入精力养的。
  • 如果公司办公网络和机房链路不稳定,节点间同步提交模式的性能损耗会被放大,业务接口延迟飙升。
  • 如果你们没有合规压力约束下对数据备份物理隔离的要求,云上托管服务自带的多副本和跨可用区能力确实是省心选项。

我自己经历过一次机房空调故障,温度报警后半个小时才降到安全范围,当时如果用的是云数据库,根本不用考虑物理环境这层。所以自建省的是钱,交出去的是环境可靠性的运维责任,这笔账要结合团队能力来算。

6.3 如果为了进一步省钱,还能做什么

如果这套架构已经搭完,后续想继续控制成本,我有几个方向可以给参考:

  • 把备份从全备加差异,改成全备加日志备份,减少备份存储占用。
  • 副本库承担报表和数据分析的读取,减少单独搭建报表库的费用。
  • 闲时把副本节点通过虚拟化平台的电源管理降低功耗,或者把非核心数据库合并到同一实例的资源池里。
  • 监控数据不要全部存商用平台,开个本地时序库,几台机器全年的监控数据存储成本很低。

我现在最满意的一点是,整个项目没有引入任何商业版运维软件,所有脚本都是 PowerShell 加 SQL 语句,出了问题可以直接翻代码排查,不用被厂商客服层层转接。

最后分享一个实操细节:Always On 节点上的 SQL Server 服务,启动类型一定要改成“自动”,而且服务恢复选项要设置成“如果服务意外停止,尝试重新启动”,我在一次 Windows 更新重启后,因为服务恢复设置不对,节点没有自动拉起数据库服务,集群直接少了一票,幸好发生在外网访问低峰期,修复及时没有造成业务中断。这种小坑,配置时多花一分钟,后面能省一整夜。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/23 13:55:59

VSCode C++环境配置:MinGW-w64 + 三JSON精准配置指南

简介:本资源是一份面向Windows 10用户的VSCode C开发环境配置实战指南,专为编程初学者与希望轻量级替代Visual Studio的开发者设计,解决C项目在VSCode中无法智能提示、编译调试等核心痛点。资源以PDF形式呈现,共1个文件&#xff0…

作者头像 李华
网站建设 2026/10/22 15:57:36

六合一综合平台外挂系统接口对接实战:认证、数据格式与异常处理

简介:这份《六合一综合平台外挂系统接口使用手册》面向交通管理综合应用平台的对接开发者与系统集成人员,聚焦外挂系统请求服务平台时的接口调用规范与数据交互问题。资源包共1个PDF文件,大小约568KB,内容涵盖接口访问地址、查询类…

作者头像 李华
网站建设 2026/10/23 13:55:59

PPT编辑密码怎么设置和取消?一文讲清修改权限密码的常见坑

做PPT这么多年,替别人紧急改文档的时候,最怕的其实是收到一个带编辑密码的PPT——打开顺畅、看内容没问题,但要改一个字、换个颜色,一保存就弹窗,只能干瞪眼。反过来,自己辛苦做好一份方案发出去&#xff0…

作者头像 李华
网站建设 2026/10/23 13:56:00

PoolFormer:用池化替代注意力的Transformer变体,图像分类实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/23 13:55:59

C++编译期类型生成:模板元编程的实战价值

C编译期类型生成,听起来像概念玩具,实际是模板元编程里最日常也最核心的能力——让编译器在编译阶段替你“算”出类型,而不是把类型判断留到程序运行。我第一次意识到这个玩法有用,是在接手一个协议解析模块的时候:32种…

作者头像 李华
网站建设 2026/10/23 13:55:59

停止等待协议实现串口文件传输:从状态机到MD5校验

简介:这份文档资料面向高校计算机网络课程的学生与实验指导教师,聚焦实验二「利用停止等待协议传输数据文件」,帮助读者在串行口编程基础上理解可靠传输机制。内容围绕停等协议的基本工作过程展开,涵盖数据包丢失、确认信息丢失或…

作者头像 李华