关键词:SQL Server for Linux、高可用、读写分离、动态扩容、Always On、可用性组
📋 文章目录
- 前言:Linux上的SQL Server不再是梦
- 高可用架构设计
- Always On 可用性组
- 故障转移集群实例
- 读写分离架构
- 可用性组读写分离
- 应用层读写分离
- 动态扩缩容方案
- 水平扩展策略
- 垂直扩展策略
- 详细实施步骤
- 环境准备与安装
- Always On配置实战
- 读写分离配置
- 监控与运维
- 故障处理与调优
- 实际部署建议
- 总结
前言:Linux上的SQL Server不再是梦
还记得几年前,如果有人说要在Linux上跑SQL Server,估计会被当作天方夜谭。但自从微软在2017年正式发布SQL Server for Linux后,这个"不可能"变成了现实。
今天我们就来聊聊,如何在Linux环境下搭建一套既稳定又灵活的SQL Server高可用架构。别担心,我们会用最接地气的方式,配合直观的架构图,让你轻松掌握这些看似复杂的技术。
高可用架构设计
Always On 可用性组
Always On可用性组可以说是SQL Server高可用的"王牌"解决方案。它允许我们将多个数据库组成一个逻辑单元,在多个SQL Server实例间进行数据同步。
架构示意图:
核心特性:
- 自动故障转移:当主节点出现问题时,系统会自动将流量切换到健康的从节点
- 数据同步模式:支持同步和异步两种复制模式,可根据性能和一致性需求灵活选择
- 读写分离支持:从节点可以承担只读查询,减轻主节点压力
故障转移集群实例
对于需要更高级别可用性保证的场景,我们可以选择故障转移集群实例(FCI)。
读写分离架构
可用性组读写分离
在Always On环境中实现读写分离相当简单,我们只需要配置读取路由即可。
配置要点:
-- 创建可用性组监听器
ALTER AVAILABILITY GROUP [MyAG]
ADD LISTENER 'AG-Listener' (WITH IP = ('192.168.1.100', '255.255.255.0'),PORT = 1433
);-- 配置只读路由
ALTER AVAILABILITY GROUP [MyAG]
MODIFY REPLICA ON 'Primary-Server'
WITH (READ_ONLY_ROUTING_URL = 'TCP://Primary-Server:1433');
应用层读写分离
当然,我们也可以在应用层面实现更灵活的读写分离策略:
动态扩缩容方案
水平扩展策略
当单台服务器性能到达瓶颈时,我们可以通过增加更多的只读副本来分担查询压力:
扩容步骤:
- 准备新节点:在新的Linux服务器上安装SQL Server
- 加入可用性组:将新节点添加到现有的可用性组中
- 更新负载均衡:修改负载均衡器配置,将新节点纳入流量分发
- 验证同步:确保数据同步正常,新节点可以正常提供服务
垂直扩展策略
对于写操作较多的场景,我们可能需要提升主节点的性能:
详细实施步骤
环境准备与安装
系统环境要求:
# 推荐使用以下Linux发行版
# Ubuntu 20.04 LTS / RHEL 8.x / SUSE Enterprise 15# 系统要求检查
echo "检查系统版本"
cat /etc/os-releaseecho "检查内存(至少4GB)"
free -hecho "检查磁盘空间(至少10GB)"
df -h
SQL Server安装步骤:
# Ubuntu环境安装
# 1. 导入GPG密钥
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -# 2. 添加SQL Server仓库
sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/20.04/mssql-server-2022.list)"# 3. 安装SQL Server
sudo apt-get update
sudo apt-get install -y mssql-server# 4. 运行初始配置
sudo /opt/mssql/bin/mssql-conf setup# 5. 验证服务状态
systemctl status mssql-server
网络配置:
# 配置防火墙规则
sudo ufw allow 1433/tcp # SQL Server默认端口
sudo ufw allow 5022/tcp # Always On端点端口
sudo ufw allow 1434/udp # SQL Browser服务# 配置主机名解析
echo "192.168.1.10 sql-primary" | sudo tee -a /etc/hosts
echo "192.168.1.11 sql-secondary1" | sudo tee -a /etc/hosts
echo "192.168.1.12 sql-secondary2" | sudo tee -a /etc/hosts
Always On配置实战
步骤1:启用Always On功能
-- 在所有节点上执行
ALTER SERVER CONFIGURATION SET HADR CLUSTER CONTEXT = 'wsfc_cluster';
GO-- 重启SQL Server服务
-- sudo systemctl restart mssql-server
步骤2:创建数据库和备份
-- 在主节点创建测试数据库
CREATE DATABASE [TestDB];
GO-- 设置为完整恢复模式
ALTER DATABASE [TestDB] SET RECOVERY FULL;
GO-- 创建完整备份
BACKUP DATABASE [TestDB]
TO DISK = '/var/opt/mssql/backup/TestDB.bak';
GO-- 创建日志备份
BACKUP LOG [TestDB]
TO DISK = '/var/opt/mssql/backup/TestDB.trn';
GO
步骤3:配置可用性组
-- 创建端点(在所有节点执行)
CREATE ENDPOINT [Hadr_endpoint]
AS TCP (LISTENER_PORT = 5022)
FOR DATA_MIRRORING (ROLE = ALL,AUTHENTICATION = CERTIFICATE [SQL_Certificate],ENCRYPTION = REQUIRED ALGORITHM AES
);
GO-- 启动端点
ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED;
GO-- 在主节点创建可用性组
CREATE AVAILABILITY GROUP [MyAG]
WITH (AUTOMATED_BACKUP_PREFERENCE = SECONDARY,DB_FAILOVER = OFF
)
FOR DATABASE [TestDB]
REPLICA ON 'sql-primary' WITH (ENDPOINT_URL = 'TCP://sql-primary:5022',AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,FAILOVER_MODE = AUTOMATIC,SECONDARY_ROLE(ALLOW_CONNECTIONS = ALL)),'sql-secondary1' WITH (ENDPOINT_URL = 'TCP://sql-secondary1:5022',AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,FAILOVER_MODE = AUTOMATIC,SECONDARY_ROLE(ALLOW_CONNECTIONS = ALL)),'sql-secondary2' WITH (ENDPOINT_URL = 'TCP://sql-secondary2:5022',AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT,FAILOVER_MODE = MANUAL,SECONDARY_ROLE(ALLOW_CONNECTIONS = ALL));
GO
步骤4:在从节点恢复数据库
# 将备份文件复制到从节点
scp /var/opt/mssql/backup/TestDB.* user@sql-secondary1:/var/opt/mssql/backup/
-- 在从节点恢复数据库
RESTORE DATABASE [TestDB]
FROM DISK = '/var/opt/mssql/backup/TestDB.bak'
WITH NORECOVERY;
GORESTORE LOG [TestDB]
FROM DISK = '/var/opt/mssql/backup/TestDB.trn'
WITH NORECOVERY;
GO-- 加入可用性组
ALTER AVAILABILITY GROUP [MyAG] JOIN;
GO-- 加入数据库到可用性组
ALTER DATABASE [TestDB] SET HADR AVAILABILITY GROUP = [MyAG];
GO
读写分离配置
创建监听器:
-- 在主节点创建监听器
ALTER AVAILABILITY GROUP [MyAG]
ADD LISTENER 'MyAG-Listener' (WITH IP = ('192.168.1.100', '255.255.255.0'),PORT = 1433
);
GO
配置只读路由:
-- 配置每个副本的只读路由URL
ALTER AVAILABILITY GROUP [MyAG]
MODIFY REPLICA ON 'sql-primary'
WITH (READ_ONLY_ROUTING_URL = 'TCP://sql-primary:1433');
GOALTER AVAILABILITY GROUP [MyAG]
MODIFY REPLICA ON 'sql-secondary1'
WITH (READ_ONLY_ROUTING_URL = 'TCP://sql-secondary1:1433');
GO-- 配置只读路由列表
ALTER AVAILABILITY GROUP [MyAG]
MODIFY REPLICA ON 'sql-primary'
WITH (READ_ONLY_ROUTING_LIST = ('sql-secondary1', 'sql-secondary2'));
GO
应用连接字符串配置:
// C# 示例
// 写操作连接字符串
string writeConnectionString = "Server=MyAG-Listener;Database=TestDB;Integrated Security=true;";// 读操作连接字符串
string readConnectionString = "Server=MyAG-Listener;Database=TestDB;Integrated Security=true;ApplicationIntent=ReadOnly;";
监控与运维
性能监控脚本
#!/bin/bash
# monitor_sqlserver.sh - SQL Server性能监控脚本LOG_FILE="/var/log/sqlserver_monitor.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')# 检查SQL Server服务状态
check_service() {if systemctl is-active --quiet mssql-server; thenecho "[$DATE] SQL Server服务正常运行" >> $LOG_FILEelseecho "[$DATE] 警告:SQL Server服务未运行" >> $LOG_FILE# 发送告警邮件或短信# send_alert "SQL Server服务异常"fi
}# 检查数据库连接
check_connection() {/opt/mssql-tools/bin/sqlcmd -S localhost -Q "SELECT @@VERSION" > /dev/null 2>&1if [ $? -eq 0 ]; thenecho "[$DATE] 数据库连接正常" >> $LOG_FILEelseecho "[$DATE] 错误:无法连接到数据库" >> $LOG_FILEfi
}# 检查可用性组状态
check_availability_group() {AG_STATUS=$(/opt/mssql-tools/bin/sqlcmd -S localhost -h -1 -Q "SELECT ag.name AS AG_Name,ar.replica_server_name,ars.role_desc,ars.operational_state_desc,ars.synchronization_health_descFROM sys.availability_groups agJOIN sys.availability_replicas ar ON ag.group_id = ar.group_idJOIN sys.dm_hadr_availability_replica_states ars ON ar.replica_id = ars.replica_id")echo "[$DATE] 可用性组状态:" >> $LOG_FILEecho "$AG_STATUS" >> $LOG_FILE
}# 执行监控
check_service
check_connection
check_availability_group
自动化备份脚本
#!/bin/bash
# auto_backup.sh - 自动备份脚本BACKUP_DIR="/var/opt/mssql/backup"
DATE=$(date '+%Y%m%d_%H%M%S')
RETENTION_DAYS=7# 创建备份目录
mkdir -p $BACKUP_DIR# 执行备份
/opt/mssql-tools/bin/sqlcmd -S localhost -Q "
BACKUP DATABASE [TestDB]
TO DISK = '$BACKUP_DIR/TestDB_Full_$DATE.bak'
WITH FORMAT, COMPRESSION;
"# 清理过期备份
find $BACKUP_DIR -name "*.bak" -mtime +$RETENTION_DAYS -deleteecho "备份完成:TestDB_Full_$DATE.bak"
资源使用监控
-- 监控数据库性能的常用查询-- 1. 检查当前连接数
SELECT COUNT(*) as CurrentConnections,(SELECT value FROM sys.configurations WHERE name = 'user connections') as MaxConnections
FROM sys.dm_exec_sessions
WHERE is_user_process = 1;-- 2. 检查等待统计
SELECT wait_type,waiting_tasks_count,wait_time_ms,max_wait_time_ms,signal_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE waiting_tasks_count > 0
ORDER BY wait_time_ms DESC;-- 3. 检查数据同步延迟
SELECT ar.replica_server_name,db_name(dr.database_id) as database_name,dr.synchronization_state_desc,dr.synchronization_health_desc,dr.log_send_queue_size,dr.redo_queue_size,dr.last_commit_time
FROM sys.dm_hadr_database_replica_states dr
JOIN sys.availability_replicas ar ON dr.replica_id = ar.replica_id;
故障处理与调优
常见故障处理
故障1:主节点宕机
# 1. 检查主节点状态
ping sql-primary# 2. 手动故障转移到从节点
/opt/mssql-tools/bin/sqlcmd -S sql-secondary1 -Q "
ALTER AVAILABILITY GROUP [MyAG] FAILOVER;
"# 3. 更新应用连接配置或DNS记录
故障2:数据同步延迟过高
-- 检查同步状态
SELECT replica_server_name,database_name,log_send_queue_size KB,log_send_rate KB_per_sec,redo_queue_size KB,redo_rate KB_per_sec
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id;-- 调整同步模式(紧急情况下)
ALTER AVAILABILITY GROUP [MyAG]
MODIFY REPLICA ON 'sql-secondary2'
WITH (AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT);
性能调优建议
数据库配置优化:
-- 1. 调整最大服务器内存
EXEC sp_configure 'max server memory (MB)', 51200; -- 50GB
RECONFIGURE;-- 2. 调整并行度
EXEC sp_configure 'max degree of parallelism', 4;
RECONFIGURE;-- 3. 优化备份压缩
EXEC sp_configure 'backup compression default', 1;
RECONFIGURE;-- 4. 调整网络包大小
EXEC sp_configure 'network packet size', 8192;
RECONFIGURE;
Linux系统优化:
# 1. 调整内核参数
echo 'vm.swappiness = 1' >> /etc/sysctl.conf
echo 'vm.dirty_ratio = 15' >> /etc/sysctl.conf
echo 'vm.dirty_background_ratio = 5' >> /etc/sysctl.conf# 2. 优化文件系统
# 建议使用XFS文件系统,挂载选项:
# /dev/sdb1 /var/opt/mssql xfs defaults,noatime,largeio,inode64 0 0# 3. 设置NUMA策略
echo 'mssql soft memlock unlimited' >> /etc/security/limits.conf
echo 'mssql hard memlock unlimited' >> /etc/security/limits.conf
实际部署建议
硬件配置建议
主节点配置:
- CPU:至少8核心,推荐16核心以上
- 内存:32GB起步,生产环境建议64GB以上
- 存储:SSD存储,IOPS不低于10000
- 网络:万兆网卡,确保数据同步性能
从节点配置:
- CPU:可适当降低,8核心即可
- 内存:与主节点保持一致或略低
- 存储:可使用相对便宜的SSD
- 网络:千兆网卡即可满足需求
网络架构设计
graph TBsubgraph "DMZ区域"WAF[Web应用防火墙]LB[负载均衡器]endsubgraph "应用服务器区域"App1[应用服务器1]App2[应用服务器2]App3[应用服务器3]endsubgraph "数据库服务器区域"Primary[主数据库]Secondary1[从数据库1]Secondary2[从数据库2]endInternet[互联网] --> WAFWAF --> LBLB --> App1LB --> App2LB --> App3App1 --> PrimaryApp1 --> Secondary1App2 --> PrimaryApp2 --> Secondary2App3 --> Primarystyle DMZ fill:#ffebeestyle "应用服务器区域" fill:#e3f2fdstyle "数据库服务器区域" fill:#f1f8e9
监控和告警
建议配置以下监控指标:
- 系统资源:CPU使用率、内存使用率、磁盘I/O、网络带宽
- 数据库指标:连接数、查询响应时间、锁等待时间、数据同步延迟
- 业务指标:TPS、QPS、错误率、可用性
总结
SQL Server for Linux的高可用架构设计并不复杂,关键在于根据业务需求选择合适的方案:
小型应用:可以选择简单的主从复制 + 读写分离
中型应用:推荐使用Always On可用性组
大型应用:建议采用多层次的高可用 + 读写分离 + 动态扩缩容
通过本文的详细实施步骤,你应该能够:
✅ 掌握安装配置:从系统准备到SQL Server安装的完整流程
✅ 理解架构设计:Always On、读写分离、扩缩容的技术原理
✅ 动手实际操作:具体的SQL命令和脚本配置
✅ 建立监控体系:性能监控、自动备份、故障处理
✅ 优化系统性能:数据库和系统级别的调优建议
记住,架构设计没有银弹,最适合的才是最好的。在实际部署时,建议:
- 先在测试环境充分验证,确保方案的可行性和稳定性
- 制定详细的变更计划,包括回滚方案
- 建立完善的监控告警,及时发现和处理问题
- 定期进行故障演练,提升团队应急处理能力
希望这篇文章不仅能够帮助你理解SQL Server for Linux的高可用架构,更能让你真正动手实施这些技术方案。如果在实际操作中遇到问题,欢迎在评论区交流讨论!