SQL Server for Linux 如何实现高可用架构

发布于:2025-06-28 ⋅ 阅读:(15) ⋅ 点赞:(0)

在这里插入图片描述


关键词:SQL Server for Linux、高可用、读写分离、动态扩容、Always On、可用性组

📋 文章目录


前言:Linux上的SQL Server不再是梦

还记得几年前,如果有人说要在Linux上跑SQL Server,估计会被当作天方夜谭。但自从微软在2017年正式发布SQL Server for Linux后,这个"不可能"变成了现实。

今天我们就来聊聊,如何在Linux环境下搭建一套既稳定又灵活的SQL Server高可用架构。别担心,我们会用最接地气的方式,配合直观的架构图,让你轻松掌握这些看似复杂的技术。


高可用架构设计

Always On 可用性组

Always On可用性组可以说是SQL Server高可用的"王牌"解决方案。它允许我们将多个数据库组成一个逻辑单元,在多个SQL Server实例间进行数据同步。

架构示意图:

异步同步
同步复制
客户端应用
负载均衡器
主节点
SQL Server Primary
从节点1
SQL Server Secondary
从节点2
SQL Server Secondary
共享存储
或本地存储
本地存储
本地存储
见证服务器

核心特性:

  • 自动故障转移:当主节点出现问题时,系统会自动将流量切换到健康的从节点
  • 数据同步模式:支持同步和异步两种复制模式,可根据性能和一致性需求灵活选择
  • 读写分离支持:从节点可以承担只读查询,减轻主节点压力

故障转移集群实例

对于需要更高级别可用性保证的场景,我们可以选择故障转移集群实例(FCI)。

客户端
虚拟IP地址
Linux集群
节点1
SQL Server Instance
节点2
SQL Server Instance
节点3
SQL Server Instance
共享存储
SAN/NFS/iSCSI
心跳检测

读写分离架构

可用性组读写分离

在Always On环境中实现读写分离相当简单,我们只需要配置读取路由即可。

写操作
读操作
读操作
数据同步
数据同步
应用程序
读写路由器
主节点
读写权限
只读副本1
只读副本2

配置要点:

-- 创建可用性组监听器
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');

应用层读写分离

当然,我们也可以在应用层面实现更灵活的读写分离策略:

应用层
数据同步
数据同步
数据同步
业务应用
写操作代理
读操作代理
主数据库
写操作
从数据库1
只读
从数据库2
只读
从数据库3
只读

动态扩缩容方案

水平扩展策略

当单台服务器性能到达瓶颈时,我们可以通过增加更多的只读副本来分担查询压力:

扩容后
扩容前
主库
负载均衡
从库1
从库2
从库3
从库4
主库
负载均衡
从库1
从库2

扩容步骤:

  1. 准备新节点:在新的Linux服务器上安装SQL Server
  2. 加入可用性组:将新节点添加到现有的可用性组中
  3. 更新负载均衡:修改负载均衡器配置,将新节点纳入流量分发
  4. 验证同步:确保数据同步正常,新节点可以正常提供服务

垂直扩展策略

对于写操作较多的场景,我们可能需要提升主节点的性能:

垂直扩展选项
CPU升级
更多核心/更高频率
内存扩容
提升缓存命中率
存储优化
SSD/NVMe
网络优化
万兆网卡
性能提升
更好的用户体验

详细实施步骤

环境准备与安装

系统环境要求:

# 推荐使用以下Linux发行版
# Ubuntu 20.04 LTS / RHEL 8.x / SUSE Enterprise 15

# 系统要求检查
echo "检查系统版本"
cat /etc/os-release

echo "检查内存(至少4GB)"
free -h

echo "检查磁盘空间(至少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;
GO

RESTORE 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');
GO

ALTER 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; then
        echo "[$DATE] SQL Server服务正常运行" >> $LOG_FILE
    else
        echo "[$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>&1
    if [ $? -eq 0 ]; then
        echo "[$DATE] 数据库连接正常" >> $LOG_FILE
    else
        echo "[$DATE] 错误:无法连接到数据库" >> $LOG_FILE
    fi
}

# 检查可用性组状态
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_desc
        FROM sys.availability_groups ag
        JOIN sys.availability_replicas ar ON ag.group_id = ar.group_id
        JOIN sys.dm_hadr_availability_replica_states ars ON ar.replica_id = ars.replica_id
    ")
    
    echo "[$DATE] 可用性组状态:" >> $LOG_FILE
    echo "$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 -delete

echo "备份完成: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 TB
    subgraph "DMZ区域"
        WAF[Web应用防火墙]
        LB[负载均衡器]
    end
    
    subgraph "应用服务器区域"
        App1[应用服务器1]
        App2[应用服务器2]
        App3[应用服务器3]
    end
    
    subgraph "数据库服务器区域"
        Primary[主数据库]
        Secondary1[从数据库1]
        Secondary2[从数据库2]
    end
    
    Internet[互联网] --> WAF
    WAF --> LB
    LB --> App1
    LB --> App2
    LB --> App3
    
    App1 --> Primary
    App1 --> Secondary1
    App2 --> Primary
    App2 --> Secondary2
    App3 --> Primary
    
    style DMZ fill:#ffebee
    style "应用服务器区域" fill:#e3f2fd
    style "数据库服务器区域" fill:#f1f8e9

监控和告警

建议配置以下监控指标:

  • 系统资源:CPU使用率、内存使用率、磁盘I/O、网络带宽
  • 数据库指标:连接数、查询响应时间、锁等待时间、数据同步延迟
  • 业务指标:TPS、QPS、错误率、可用性

总结

SQL Server for Linux的高可用架构设计并不复杂,关键在于根据业务需求选择合适的方案:

小型应用:可以选择简单的主从复制 + 读写分离
中型应用:推荐使用Always On可用性组
大型应用:建议采用多层次的高可用 + 读写分离 + 动态扩缩容

通过本文的详细实施步骤,你应该能够:

掌握安装配置:从系统准备到SQL Server安装的完整流程
理解架构设计:Always On、读写分离、扩缩容的技术原理
动手实际操作:具体的SQL命令和脚本配置
建立监控体系:性能监控、自动备份、故障处理
优化系统性能:数据库和系统级别的调优建议

记住,架构设计没有银弹,最适合的才是最好的。在实际部署时,建议:

  1. 先在测试环境充分验证,确保方案的可行性和稳定性
  2. 制定详细的变更计划,包括回滚方案
  3. 建立完善的监控告警,及时发现和处理问题
  4. 定期进行故障演练,提升团队应急处理能力

希望这篇文章不仅能够帮助你理解SQL Server for Linux的高可用架构,更能让你真正动手实施这些技术方案。如果在实际操作中遇到问题,欢迎在评论区交流讨论!