资讯动态

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

发布时间:2026/10/9 3:37:34 来源:尧图企业网站定制
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 nameCluster RPC dirin actionallow protocolTCP localport3343 netsh advfirewall firewall add rule nameCluster RPC Dynamic dirin actionallow protocolTCP localport49152-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。多子网部署时勾选“启用多子网故障转移”客户端连接字符串里也要加上 MultiSubnetFailoverTrue这个是很多开发同事容易漏掉的地方。我们应用服务器和数据库在同一网段属于单子网简单不少。但为了让只读请求也能分流我在监听器下面配置了只读路由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)));开发那边把报表连接的连接字符串改成Servertcp:AGListener,1433;DatabaseCoreDB;ApplicationIntentReadOnly;MultiSubnetFailoverTrue;加了 ApplicationIntentReadOnly查询请求就会自动落到副本不会再往主库上堆负载。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 更新重启后因为服务恢复设置不对节点没有自动拉起数据库服务集群直接少了一票幸好发生在外网访问低峰期修复及时没有造成业务中断。这种小坑配置时多花一分钟后面能省一整夜。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑