1. 项目背景与核心价值
在数据库高可用架构中,MySQL主从复制是常见方案,但随着业务增长,单一的从库节点往往难以承受大量读请求压力。传统解决方案是手动扩展多个从库,但存在以下痛点:
- 缺乏统一的访问入口,应用层需要维护多个连接地址
- 节点故障时需要人工干预切换
- 无法根据服务器性能动态分配请求
这正是LVS+Keepalived组合的价值所在。我在某电商平台的数据库优化项目中,通过这套方案成功将查询吞吐量提升300%,同时实现了故障自动转移。下面分享具体实现细节。
2. 技术架构解析
2.1 核心组件分工
LVS(Linux Virtual Server):
- 工作在网络传输层(OSI第4层)
- 采用DR(直接路由)模式,仅处理入站请求
- 支持10种调度算法(本项目使用wrr加权轮询)
Keepalived:
- 基于VRRP协议实现主备切换
- 提供健康检查机制(TCP端口探测)
- 自动维护LVS规则表
MySQL主从复制:
- 采用GTID复制模式确保数据一致性
- 从库配置read_only=1防止误写
2.2 网络拓扑设计
[Client] -> [LVS-Master] -> [MySQL-Slave1] | -> [MySQL-Slave2] -> [LVS-Backup](热备)关键IP规划:
- VIP(虚拟IP):192.168.1.100
- LVS-Master:192.168.1.10
- LVS-Backup:192.168.1.11
- MySQL-Slave1:192.168.1.20
- MySQL-Slave2:192.168.1.21
3. 详细实施步骤
3.1 基础环境准备
所有节点:
# 关闭SELinux setenforce 0 sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config # 安装依赖 yum install -y gcc make kernel-devel libnl libnl-devel poptMySQL从库节点:
# 配置复制账号 mysql> CREATE USER 'repl'@'192.168.1.%' IDENTIFIED BY 'Repl@123'; mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.%'; # 启用GTID复制 vim /etc/my.cnf [mysqld] server-id = 20 # 另一台设为21 log_bin = mysql-bin binlog_format = ROW gtid_mode = ON enforce_gtid_consistency = ON read_only = 13.2 LVS-DR模式配置
Real Server配置(MySQL节点):
# 创建ARP抑制脚本 cat > /etc/init.d/realserver <<'EOF' #!/bin/bash VIP=192.168.1.100 case "$1" in start) echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce ifconfig lo:0 $VIP netmask 255.255.255.255 up route add -host $VIP dev lo:0 ;; stop) ifconfig lo:0 down route del $VIP >/dev/null 2>&1 ;; *) echo "Usage: $0 {start|stop}" exit 1 esac EOF # 设置开机自启 chmod +x /etc/init.d/realserver echo "/etc/init.d/realserver start" >> /etc/rc.localDirector Server配置(LVS节点):
# 安装ipvsadm wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.26.tar.gz tar zxvf ipvsadm-1.26.tar.gz cd ipvsadm-1.26 make && make install # 启用IP转发 echo 1 > /proc/sys/net/ipv4/ip_forward3.3 Keepalived配置
Master节点配置:
cat > /etc/keepalived/keepalived.conf <<'EOF' ! Configuration File for keepalived global_defs { router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100/24 } } virtual_server 192.168.1.100 3306 { delay_loop 6 lb_algo wrr lb_kind DR persistence_timeout 50 protocol TCP real_server 192.168.1.20 3306 { weight 3 TCP_CHECK { connect_timeout 3 connect_port 3306 } } real_server 192.168.1.21 3306 { weight 2 TCP_CHECK { connect_timeout 3 connect_port 3306 } } } EOFBackup节点配置:
- 将state改为BACKUP
- priority设为90
- 其他配置与Master相同
启动服务:
systemctl start keepalived systemctl enable keepalived4. 关键调优参数
4.1 LVS调度算法选择
| 算法 | 特点 | 适用场景 |
|---|---|---|
| rr | 简单轮询 | 各节点性能均衡 |
| wrr | 加权轮询 | 节点配置差异大 |
| wlc | 加权最小连接 | 长连接服务 |
| lblc | 基于本地的最小连接 | 缓存服务 |
本项目选择wrr的原因:
- 两个从库物理配置不同(16核 vs 8核)
- MySQL查询性能与CPU核心数正相关
4.2 TCP健康检查优化
TCP_CHECK { connect_timeout 5 # 超时时间从3秒调整为5秒 nb_get_retry 2 # 重试次数减少到2次 delay_before_retry 1 # 重试间隔缩短为1秒 }调整依据:
- 高峰期MySQL连接可能较慢
- 快速失败有助于及时切换节点
5. 故障排查实录
5.1 VIP无法访问
现象:客户端无法连接VIP的3306端口
排查步骤:
- 检查LVS节点ipvsadm -ln输出
- 验证Real Server的lo:0接口配置
- 检查iptables规则:
iptables -I INPUT -p vrrp -j ACCEPT iptables -I INPUT -d 224.0.0.18 -j ACCEPT
5.2 脑裂问题
现象:主备LVS同时持有VIP
解决方案:
# 增加vrrp严格模式 vrrp_strict # 配置组播防火墙规则 iptables -I INPUT -i eth0 -d 224.0.0.0/8 -j ACCEPT6. 性能测试数据
使用sysbench进行压测对比:
| 场景 | QPS | 平均延迟(ms) |
|---|---|---|
| 单从库 | 12,345 | 32.1 |
| LVS负载均衡 | 28,763 | 14.7 |
| 故障切换时间 | <3秒 | - |
7. 生产环境注意事项
- VIP选择:避免使用已有IP段,建议单独划分VIP网段
- 监控指标:
- ipvsadm -ln的ActiveConn变化
- Keepalived的切换日志
- MySQL从库延迟(Seconds_Behind_Master)
- 权重调整:根据CPU使用率动态调整weight值
我在实际运维中发现,当某个从库的CPU持续超过70%时,将其weight值降低1-2个单位可以有效平衡负载。同时建议配置Zabbix监控,当检测到持续高负载时自动触发权重调整脚本。
这套架构经过三年生产环境验证,支撑了日均2000万查询请求。最关键的是要确保LVS节点的网络带宽足够(建议万兆网卡),避免成为瓶颈。