企业级高可用实战:Keepalived + LVS(DR)+ MariaDB 主主架构深度解析

企业级高可用实战:Keepalived + LVS(DR)+ MariaDB 主主架构深度解析

引言

在企业级应用中,数据库作为业务数据的"核心载体",其高可用性、读写性能和数据一致性直接决定业务能否稳定运行。无论是电商交易系统(订单生成、库存扣减)、金融支付平台(交易对账、资金流转),还是政务管理系统(数据上报、业务审批),**"数据库一旦宕机,业务就瘫痪"**已成为不可触碰的红线。传统的单节点或简单主从架构,已经无法满足现代互联网高并发、高可用的刚性需求。本文将基于实际操作,详细拆解通过 Keepalived(VIP 漂移) + LVS(DR 模式流量分发) + MariaDB 主主复制(双活写) 构建的稳固企业级架构。


第一部分:项目背景与架构选型逻辑

1. 业务场景与数据库核心诉求

在业务演进过程中,数据库会面临以下四大类刚性需求:

  • 无间断服务(高可用) :数据库需实现7×24小时不间断运行,避免因单点故障(如数据库服务器宕机、磁盘损坏、网络中断)导致业务中断。例如:电商平台秒杀活动中,若数据库不可用,将直接导致订单无法生成,每中断1分钟可能造成数万元营收损失;金融系统中,数据库故障可能引发交易对账异常,甚至触发合规风险。
  • 高并发承载(读写性能):随着用户规模增长,数据库面临的读写请求呈指数级上升(如日均SQL执行量从100万次增至1亿次)。单台数据库的CPU、内存、IO能力易成为瓶颈:读请求过多会导致查询延迟(如用户查询订单列表超时),写请求集中会造成事务阻塞(如多用户同时提交订单导致库存更新排队)。
  • 数据零丢失(可靠性):业务数据需具备"抗丢失"能力,即使遭遇硬件故障或软件异常,也需保证数据不损坏、不丢失。例如:用户充值记录、订单信息若因数据库故障丢失,将直接引发用户投诉与信任危机;同时,多节点间的数据需实时同步,避免出现"主库数据已更新,从库仍展示旧数据"的一致性问题。
  • 灵活扩展(可扩展性):业务增长过程中,需支持"按需扩展"数据库能力:读压力增大时可快速新增读节点,写压力上升时可优化写分发策略,避免因架构僵化导致"业务倒逼重构"的被动局面。

2. 传统数据库架构的致命痛点与局限

在采用本方案前,多数企业曾使用"单节点数据库"或"简单主从架构",但面临以下难以突破的瓶颈:

① 单节点数据库:单点故障风险致命

  • 风险:数据库仅部署在一台服务器上,一旦硬件故障(如电源损坏、磁盘坏道)或软件崩溃(如MariaDB进程异常退出),将导致全量业务中断。
  • 恢复效率极低:依赖人工干预恢复(如更换服务器、重建数据库、恢复备份),平均恢复时间(MTTR)通常超过30分钟,远无法满足"秒级切换"的业务需求;若备份数据不完整,还可能导致部分业务数据永久丢失。

② 简单主从架构(一主一从):读写瓶颈与切换缺陷

  • 读性能局限 :虽然通过"主库写、从库读"分摊读压力,但从库仅能扩展读能力,无法缓解主库的写压力(如大量订单写入仍集中在主库);且从库数量增多时,缺乏统一的读请求分发机制,易导致部分从库过载(如某台从库承担80%读请求)、部分从库空闲。
  • 高可用缺陷:主库故障时,需手动将从库提升为新主库,再修改业务系统的数据库连接地址,切换过程耗时且易出错(如忘记同步从库未应用的binlog导致数据不一致);同时,从库仅作为"备用节点",写请求始终依赖主库,主库写瓶颈无法突破。

③ 无负载均衡:请求分发混乱

  • 硬编码问题:部分企业尝试用"业务层硬编码连接地址"实现读写分离(如读请求连从库IP,写请求连主库IP),但存在两大问题:一、缺乏故障检测机制,若某台从库宕机,业务层无法实时感知,仍会将读请求分发至故障节点,导致部分读业务失败;二、扩展性差,新增读节点时,需修改业务代码中的连接地址列表,重启服务才能生效,不符合"无感知扩展"的运维需求。

④ 数据同步与一致性风险

  • 数据断层:传统主从架构依赖MariaDB原生的binlog同步,若网络延迟或主库binlog丢失,会导致从库数据滞后或同步失败;且主库故障时,若从库未完全同步主库数据,强制切换会造成"数据断层"(如主库已提交的订单,从库未记录),引发严重商业事故。

3. 技术方案的选型逻辑

针对上述痛点,需构建一套"高可用负载均衡 + 双主互备 + 读写协同"的数据库架构。我们最终选型 《Keepalived + LVS(DR) + MariaDB主主》 组合,正是基于以下核心诉求:

  • 为什么选择 MariaDB 主主(突破写瓶颈与双活备份)
    采用"双主互备"模式(两台MariaDB均为主库,可同时处理写请求),彻底解决传统主从架构的"写依赖单主"问题,写性能理论上提升2倍;两台主库实时同步数据(通过binlog双向同步),任一主库故障时,另一主库已拥有完整数据,避免数据丢失;同时,支持"读写请求均分发至双主",进一步提升整体并发能力。
  • 为什么选择 LVS(DR模式)(高效分发读写请求)
    LVS作为四层负载均衡器,基于IP和端口转发请求,具备超高并发承载能力(单机可支撑10万+并发连接) ,远超Nginx等七层负载均衡器;采用DR(直接路由)模式,请求仅经过LVS转发至后端MariaDB节点,响应数据直接从MariaDB返回给客户端,避免"请求回程流量"占用LVS带宽,转发效率接近物理机直连;支持"健康检查",实时检测MariaDB节点状态,若某台主库宕机,LVS自动将请求分发至另一台健康主库,避免业务访问故障节点。
  • 为什么选择 Keepalived(负载均衡层高可用)
    LVS作为请求分发核心,若自身单点故障,将导致全量数据库请求无法转发。通过Keepalived的VRRP协议实现LVS主备高可用:主LVS节点故障时,备LVS节点可在1-3秒内自动接管虚拟IP(VIP),实现"无感知切换",彻底消除负载均衡层单点风险;支持"优先级配置",可根据LVS节点性能设置主备角色,确保高性能节点优先承担转发任务。

4. 项目预期价值与目标

通过部署本架构,预期实现以下技术与业务价值:

  1. 高可用升级 :数据库层可用性从 99.9% 提升至 99.99% ,年均故障中断时间从8.76小时降至 52.56分钟,核心业务(如订单、支付)无服务中断风险。
  2. 性能翻倍 :写性能从单主 500TPS 提升至双主 1000+ TPS,读性能支持通过新增从节点无限扩展(LVS统一分发读请求),95% SQL查询响应时间 < 200ms。
  3. 数据可靠:双主实时同步数据,任一节点故障无数据丢失;LVS健康检查 + Keepalived主备切换,实现"故障自动转移",无需人工干预。
  4. 运维高效 :新增数据库节点时,仅需接入LVS集群,无需修改业务代码;负载均衡与数据库节点状态可通过监控平台实时查看,故障定位效率提升 70%

第二部分:项目环境与节点规划

1. 实验拓扑概述

本实验基于 VMware 虚拟化环境,划分了 10.1.8.0/24(业务网)和 10.1.1.0/24(外部网)两个网段。由 router 负责开启路由转发和 NAT,连接外部客户端与内部业务集群;ha1ha2 组成 LVS/Keepalived 双机热备层;db1db2 组成 MariaDB 数据层。

2. 节点规划表

主机名 IP 地址 网关 DNS VIP 地址 服务器角色
client1 10.1.8.21 (vmnet8) 10.1.8.20 223.5.5.5 客户端
client2 10.1.1.21 (vmnet1) 10.1.1.20 223.5.5.5 客户端
router 10.1.8.20 / 10.1.1.20 10.1.8.2 223.5.5.5 路由器(开启转发与NAT)
ha1 10.1.8.13 (vmnet8) 10.1.8.20 223.5.5.5 10.1.8.100 LVS+Keepalived 主服务器
ha2 10.1.8.14 (vmnet8) 10.1.8.20 223.5.5.5 10.1.8.100 LVS+Keepalived 备服务器
db1 10.1.8.11 (vmnet8) 10.1.8.20 223.5.5.5 10.1.8.100 DB 主服务器
db2 10.1.8.12 (vmnet8) 10.1.8.20 223.5.5.5 10.1.8.100 DB 从服务器

3. 基础环境准备

所有节点均使用 CentOS 7 模板机,需先配置好主机名、网卡 IP 和网关。特别注意: 路由器 router 需要开启系统内核 IP 转发功能,并关闭防火墙限制。

bash 复制代码
# 在 router 上开启路由转发
[root@router ~ 19:29:32]# vim /etc/sysctl.conf 
net.ipv4.ip_forward=1
[root@router ~ 19:30:30]# sysctl -p
net.ipv4.ip_forward = 1

第三部分:后续实操内容框架

步骤一:MariaDB 安装与双主(主主)复制配置

1. 安装与安全初始化

分别在 db1db2 上安装 mariadb-server,并开启二进制日志。

bash 复制代码
[root@db1 ~ 19:32:56]# yum install -y mariadb-server
[root@db2 ~ 19:32:56]# yum install -y mariadb-server

# 开启二进制日志和 relay log
[root@db1 ~ 19:35:56]# vim /etc/my.cnf.d/server.cnf 
[mysqld]
server-id=1          # db2 上修改为 2
log_bin=mysql-bin
relay_log=mysql-relay-bin

# 启动服务并运行安全初始化脚本
[root@db1 ~ 19:36:49]# systemctl enable mariadb.service --now
[root@db1 ~ 19:36:55]# mysql_secure_installation

2. 配置 db2 -> db1 复制

登录 db1 创建复制用户并查看位点,然后到 db2 配置 CHANGE MASTER。

sql 复制代码
-- 在 db1 执行
MariaDB [(none)]> grant replication slave, replication client on *.* to 'repl'@'10.1.8.12' identified by 'huawei';
MariaDB [(none)]> show master status\G;
*************************** 1. row ***************************
        File: mysql-bin.000003
        Position: 1650
    	Binlog_Do_DB: 
		Binlog_Ignore_DB: 
	1 row in set (0.00 sec)

-- 记下 File 和 Position

-- 在 db2 执行
MariaDB [(none)]> change master to master_host='10.1.8.11', master_user='repl', master_password='huawei', master_port=3306, master_log_file='mysql-bin.000003', master_log_pos=1650, master_connect_retry=30;
MariaDB [(none)]> start slave;
MariaDB [(none)]> show slave status\G;
-- 确保 Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.1.8.11
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 1650
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 529
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1650
              Relay_Log_Space: 823
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1

3. 配置 db1 -> db2 复制(主主反向)

反向操作一遍,将 db2 作为主库,db1 作为从库。

bash 复制代码
# 在 db2 上创建 repl 用户(授权给 10.1.8.11)
# 在 db1 上执行 CHANGE MASTER TO MASTER_HOST='10.1.8.12'...

验证数据同步:在主库建库建表插入数据,在从库查询,确认已自动同步。


步骤二:配置 LVS-RS(真实后端服务器)

最关键的一步! 在 DR 模式下,所有的 Real Server(db1 和 db2)都必须在 lo 接口上绑定 VIP,并抑制 ARP 响应,防止路由器把 VIP 的 MAC 错误映射到 RS 上。

bash 复制代码
# 增加虚拟网卡(绑定 VIP 到 lo)
[root@db1 ~ 19:46:36]# nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32
[root@db1 ~ 19:46:42]# nmcli connection up dummy

# 配置 ARP 参数,抑制响应
[root@db1 ~ 19:46:48]# cat >> /etc/sysctl.conf << EOF
> net.ipv4.conf.all.arp_ignore = 1
> net.ipv4.conf.all.arp_announce = 2
> net.ipv4.conf.dummy.arp_ignore = 1
> net.ipv4.conf.dummy.arp_announce = 2
> EOF
[root@db1 ~ 19:47:28]# sysctl -p
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.dummy.arp_ignore = 1
net.ipv4.conf.dummy.arp_announce = 2

# db2操作相同

(db2 也需执行相同配置。)


步骤三:配置 Keepalived 和 LVS-DS(调度器)

ha1ha2 上安装 keepalivedipvsadm

1. 配置 ha1(Master 节点)

bash 复制代码
[root@ha1 ~ 19:27:10]# yum install -y keepalived ipvsadm
[root@ha1 ~ 19:49:21]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
   router_id ha1
}

vrrp_instance db {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 110
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.1.8.100/24
    }
}

virtual_server 10.1.8.100 3306 {
    delay_loop 6
    lb_algo rr
    lb_kind DR
    persistence_timeout 50
    protocol TCP

    real_server 10.1.8.11 3306 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
    real_server 10.1.8.12 3306 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

2. 配置 ha2(Backup 节点)

复制 ha1 的配置,仅修改 router_idha2,将 state MASTER 改为 state BACKUPpriority 110 改为 priority 100

3. 启动与验证

bash 复制代码
# 分别在 ha1 和 ha2 上执行
[root@ha1 ~ 19:52:00]# systemctl enable keepalived.service --now

# 查看 VIP 是否正确绑定
[root@ha1 ~ 19:52:12]# ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128 
ens33            UP             10.1.8.13/24 10.1.8.100/24 fe80::baf4:a2c5:6e5c:ea60/64 fe80::6f9c:c7bf:36f9:e430/64 
[root@ha2 ~ 19:52:12]# ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128 
ens33            UP             10.1.8.14/24 fe80::baf4:a2c5:6e5c:ea60/64 fe80::6f9c:c7bf:36f9:e430/64 fe80::878c:d585:6df9:4cf3/64

# 查看 LVS 规则是否生效
[root@ha1 ~]# ipvsadm -Ln
[root@ha1 ~ 19:52:29]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.8.100:3306 rr persistent 50
  -> 10.1.8.11:3306               Route   1      0          0         
  -> 10.1.8.12:3306               Route   1      0          0         
[root@ha2 ~ 19:52:29]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.8.100:3306 rr persistent 50
  -> 10.1.8.11:3306               Route   1      0          0         
  -> 10.1.8.12:3306               Route   1      0          0         

步骤四:高可用与负载均衡验证

  1. 基础连通性测试 :在客户端 client1 上使用 mysql -ulaogao -phuawei -h 10.1.8.100 连接数据库,验证轮询调度。
  2. LVS 单点故障切换测试 :在 ha1 上执行 systemctl stop keepalived,再次在客户端连接 VIP,应能自动切换到 ha2 并保持数据库连接不断。
  3. DB 节点故障自动摘除测试 :停止 db1 上的 MariaDB 服务。LVS 健康检查会将 db1 剔除集群,后续客户端请求全部自动转发至 db2,业务无感知,数据零丢失。

第四部分:排错与避坑指南(总结)

  1. 防火墙与 SELinux :实验环境务必在 LVS 和 RS 上先执行 systemctl stop firewalldsetenforce 0,否则健康检查不通过,后端会被踢出。
  2. ARP 抑制 :DR 模式下的 Real Server 忘记配置 arp_ignore=1 会导致 VIP 冲突,出现请求转发不过去或者网络不通的现象。
  3. 端口匹配virtual_server 的端口必须和真实后端数据库监听的 3306 端口完全一致。(如果你后期的实验在 80 端口跑 Nginx 反向代理,就需要专门配一个 virtual_server 10.1.8.100 80 块!)
相关推荐
程序员无隅26 分钟前
从工具循环到上下文压缩:读懂 Pi 编程 Agent 的内部架构
ai·架构
mldong27 分钟前
跨语言对齐方法论:参考实现先行 + 契约测试
java·架构
黑马程序员毕设31 分钟前
基于B/S架构的“指尖乡味”助农电商小程序系统设计与实现
spring boot·微信小程序·小程序·架构·课程设计·毕设
xu_wenming8 小时前
嵌入式软件架构中的6种解耦艺术
c语言·驱动开发·嵌入式硬件·架构
ZGIAI9 小时前
ZGI Workflow 变量池:接住节点输出
人工智能·架构
ZGIAI9 小时前
ZGI 记忆隔离:多人共用不串号
人工智能·架构
星栈独行10 小时前
决定 Agent 交付下限的「操作系统」:Harness 六层架构拆解
人工智能·架构
Cicada12810 小时前
配置文件格式选择指南:JSON、YAML、TOML、INI、ENV、XML
架构
美狐美颜SDK开放平台12 小时前
视频美颜SDK是什么?直播APP开发中美颜功能实现方式介绍
深度学习·架构·实时互动·音视频·视频美颜sdk