企业级数据库高可用架构实战|Keepalived+LVS(DR)+MariaDB主主全套搭建,每行命令逐参数拆解
哈喽各位小伙伴!👋 今天这篇绝对是 运维进阶必看的硬核干货!
你是不是也遇到过这些头疼的问题:
- 😫 数据库单台部署,一宕机全业务瘫痪,老板追着你跑?
- 😱 主从切换要手动改配置,手忙脚乱还容易出错?
- 🤯 LVS、Keepalived、MariaDB主主……这些名词听着就头大,不知道怎么组合?
别慌!今天这篇文章我将用 最通俗的语言 + 最详细的命令注释,带你从零搭建一套 企业级数据库高可用集群:
Keepalived(高可用)+ LVS-DR(四层负载均衡)+ MariaDB主主复制(双活数据同步)每一行命令都给你掰碎了讲,小白也能轻松跟上~建议先收藏⭐再看!
📚 全文知识地图
先给大家上一张"导航图",看看我们今天要征服哪些知识点:
| 模块 | 核心内容 | 运维实战价值 | 难度指数 |
|---|---|---|---|
| 项目背景 | 传统数据库痛点、方案选型逻辑 | 理解为什么要这么搭,面试高频考点 | ⭐⭐ |
| MariaDB主主复制 | 主从原理、双向同步配置 | 数据库双活,写性能翻倍,数据零丢失 | ⭐⭐⭐ |
| LVS-DR模式 | 四层负载均衡、DR直接路由原理 | 万级并发转发,响应不经过LVS,性能极高 | ⭐⭐⭐ |
| Keepalived高可用 | VRRP协议、VIP漂移、健康检查 | 消除LVS单点故障,秒级自动切换 | ⭐⭐⭐ |
| 综合故障测试 | LVS节点宕机、数据库节点宕机 | 验证高可用效果,生产验收必做 | ⭐⭐⭐⭐ |
💡 小贴士:本文所有命令都在 CentOS 7 环境下验证通过,所有主机名中的
laogao已统一替换为jhl,放心抄作业!
🏗️ 第一部分:项目背景与方案选型
🤔 1.1 业务场景与数据库核心诉求
在企业级应用中,数据库作为业务数据的 “核心载体”,其高可用性、读写性能、数据一致性直接决定业务能否稳定运行。
无论是电商交易系统(订单生成、库存扣减)、金融支付平台(交易对账、资金流转),还是政务管理系统(数据上报、业务审批),都对数据库提出以下 四大刚性需求:
| 需求 | 详细说明 | 真实场景举例 |
|---|---|---|
| 无间断服务(高可用) | 数据库需实现24×7小时不间断运行,避免单点故障导致业务中断 | 电商秒杀中数据库不可用,每分钟损失数万元营收 |
| 高并发承载(读写性能) | 用户规模增长,读写请求指数级上升,单台CPU/内存/IO易成瓶颈 | 日均SQL从100万次增至1亿次,查询超时、事务阻塞 |
| 数据零丢失(可靠性) | 硬件故障或软件异常时,保证数据不损坏、不丢失,多节点实时同步 | 用户充值记录丢失,引发投诉与信任危机 |
| 灵活扩展(可扩展性) | 读压力大可快速加读节点,写压力大可优化写分发策略 | 业务增长倒逼架构重构,被动局面 |
⚠️ 1.2 传统数据库架构的痛点与局限
在采用《Keepalived + LVS(DR)+ MariaDB主主》方案前,多数企业使用 “单节点数据库” 或 “简单主从架构”,面临以下难以突破的瓶颈:
痛点1:单节点数据库——单点故障风险致命
问题核心:数据库仅部署在一台服务器上,一旦硬件故障(电源损坏、磁盘坏道)或软件崩溃(MariaDB进程异常退出),全量业务中断。
恢复效率低:依赖人工干预恢复(更换服务器、重建数据库、恢复备份),平均恢复时间(MTTR)通常超过30分钟,远无法满足"秒级切换"需求;若备份不完整,还可能导致部分业务数据永久丢失。
痛点2:简单主从架构(一主一从)——读写瓶颈与切换缺陷
| 问题 | 详细说明 |
|---|---|
| 读性能局限 | 主库写、从库读分摊读压力,但从库无法缓解主库写压力;从库增多时缺乏统一分发机制,部分从库过载、部分空闲 |
| 高可用缺陷 | 主库故障需手动将从库提升为新主库,再修改业务连接地址,切换耗时且易出错(忘记同步binlog导致数据不一致) |
| 写瓶颈 | 从库仅作备用,写请求始终依赖主库,主库写瓶颈无法突破 |
痛点3:无负载均衡——请求分发混乱
部分企业用"业务层硬编码连接地址"实现读写分离,但存在两大问题:
- 缺乏故障检测:某台从库宕机,业务层无法实时感知,仍将请求分发至故障节点;
- 扩展性差:新增读节点需修改业务代码、重启服务,不符合"无感知扩展"需求。
痛点4:数据同步与一致性风险
传统主从依赖MariaDB原生binlog同步,网络延迟或binlog丢失会导致从库数据滞后;主库故障时,若从库未完全同步,强制切换会造成"数据断层"。
🎯 1.3 技术方案的选型逻辑
针对上述痛点,需构建一套 “高可用负载均衡 + 双主互备 + 读写协同” 的数据库架构,《Keepalived + LVS(DR)+ MariaDB主主》组合正是基于以下核心诉求选型:
选型1:MariaDB主主——突破写瓶颈与双活备份
- 采用 “双主互备” 模式(两台MariaDB均为主库,可同时处理写请求),彻底解决传统主从"写依赖单主"问题,写性能理论提升2倍;
- 两台主库通过binlog 双向实时同步,任一主库故障时,另一主库已拥有完整数据,避免数据丢失;
- 支持"读写请求均分发至双主",进一步提升整体并发能力。
选型2:LVS(DR模式)——高效分发读写请求
- LVS作为 四层负载均衡器,基于IP和端口转发请求,单机可支撑 10万+并发连接,远超Nginx等七层负载均衡器;
- 采用 DR(直接路由)模式:请求仅经过LVS转发至后端MariaDB,响应数据直接从MariaDB返回客户端,避免"回程流量"占用LVS带宽,转发效率接近物理机直连;
- 支持 健康检查,实时检测MariaDB节点状态,某台主库宕机自动将请求分发至另一台健康主库。
选型3:Keepalived——负载均衡层高可用
- LVS作为请求分发核心,若自身单点故障,全量数据库请求无法转发;
- 通过Keepalived的 VRRP协议 实现LVS主备高可用:主LVS节点故障时,备LVS节点可在 1-3秒内 自动接管虚拟IP(VIP),实现"无感知切换";
- 支持 优先级配置,可根据LVS节点性能设置主备角色。
📊 1.4 项目价值与预期目标
| 价值维度 | 预期效果 |
|---|---|
| 高可用升级 | 数据库可用性从99.9%提升至99.99%,年均故障中断从8.76小时降至52.56分钟 |
| 性能翻倍 | 写性能从单主500 TPS提升至双主1000+ TPS,95% SQL查询响应<200ms |
| 数据可靠 | 双主实时同步,任一节点故障无数据丢失;LVS健康检查+Keepalived切换,无需人工干预 |
| 运维高效 | 新增数据库节点仅需接入LVS集群,无需修改业务代码;故障定位效率提升70% |
🔧 第二部分:MariaDB主从复制原理(先懂原理再动手)
🤔 2.1 什么是主从复制?
MariaDB主从复制是指:主库将数据变更以日志形式传输给从库,从库重放日志实现数据一致。
核心组件对照表
| 组件 | 所在节点 | 作用 |
|---|---|---|
| 二进制日志(binlog) | 主库 | 记录所有修改数据的SQL(增删改、建表等),是主从同步的"数据源头" |
| 中继日志(relay log) | 从库 | 从库本地日志,存储从主库获取的binlog内容,避免直接通过网络读取主库binlog |
| binlog dump线程 | 主库 | 负责向从库传输binlog |
| IO线程 | 从库 | 负责连接主库、拉取binlog并写入本地relay log |
| SQL线程 | 从库 | 负责读取relay log、执行其中的SQL,还原主库数据变更 |
📋 2.2 主从同步完整5步流程
主库执行写操作 → 写入binlog → 从库IO线程拉取 → 写入relay log → SQL线程重放 → 数据一致
| 步骤 | 详细说明 |
|---|---|
| 步骤1:主库记录binlog | 主库执行数据变更(INSERT/UPDATE/DELETE/CREATE TABLE),操作先写入redo log保证持久化,事务提交时按顺序写入binlog |
| 步骤2:从库IO线程连接主库 | 从库启动后,IO线程主动连接主库,发送要同步的binlog文件名和位置(position);首次全量同步,后续仅增量同步 |
| 步骤3:主库dump线程传输binlog | 主库接收到请求后创建binlog dump线程,根据从库指定的文件和位置读取增量binlog,通过网络传输给从库IO线程 |
| 步骤4:从库IO线程写入relay log | 从库IO线程接收到binlog后,先写入本地relay log(避免网络中断丢数据),同时更新master.info/relay-log.info记录同步位置 |
| 步骤5:从库SQL线程重放relay log | 从库SQL线程实时读取relay log,按顺序解析并执行其中的事件,还原主库数据变更,执行后更新relay-log.info标记已处理位置 |
💡 主主复制的本质:只需要把主节点当做从节点、从节点当做主节点 再做一遍,就能实现双向同步!
🖥️ 第三部分:项目环境与基础配置
📋 3.1 项目环境总览
| 主机名 | IP地址 | 网关 | DNS | VIP地址 | 服务器角色 |
|---|---|---|---|---|---|
| client2.jhl.cloud | 10.1.1.21(vmnet1) | 10.1.1.20 | 223.5.5.5 | 无 | 客户端 |
| client1.jhl.cloud | 10.1.8.21(vmnet8) | 10.1.8.20 | 223.5.5.5 | 无 | 客户端 |
| router.jhl.cloud | 10.1.8.20(vmnet8) 10.1.1.20(vmnet1) | 10.1.8.2 无网关 | 223.5.5.5 无DNS | 无 | 路由器 |
| ha1.jhl.cloud | 10.1.8.13(vmnet8) | 10.1.8.20 | 223.5.5.5 | 10.1.8.100 | LVS+Keepalived服务器(主) |
| ha2.jhl.cloud | 10.1.8.14(vmnet8) | 10.1.8.20 | 223.5.5.5 | 10.1.8.100 | LVS+Keepalived服务器(备) |
| db1.jhl.cloud | 10.1.8.11(vmnet8) | 10.1.8.20 | 223.5.5.5 | 10.1.8.100 | 数据库服务器(主主1) |
| db2.jhl.cloud | 10.1.8.12(vmnet8) | 10.1.8.20 | 223.5.5.5 | 10.1.8.100 | 数据库服务器(主主2) |
📌 架构说明:
10.1.8.0/24网段(vmnet8)是核心业务网段,包含LVS、数据库、客户端;10.1.1.0/24网段(vmnet1)是另一个客户端网段,通过router路由器访问核心网段;- VIP
10.1.8.100是数据库统一访问入口,由Keepalived管理,正常在ha1上;- db1和db2配置dummy虚拟网卡绑定VIP,用于LVS-DR模式的响应直接返回。
🧪 3.2 完整实验思路总览
第1步:7台机器基础配置(主机名+静态IP)
↓
第2步:配置router路由器(开启IP转发+地址伪装)
↓
第3步:db1和db2安装MariaDB并安全初始化
↓
第4步:配置第一组主从(db1主 → db2从)
↓
第5步:配置第二组主从(db2主 → db1从)→ 形成主主复制
↓
第6步:db1和db2配置LVS-RS(dummy网卡+ARP抑制)
↓
第7步:ha1和ha2安装Keepalived+ipvsadm,配置LVS-DR
↓
第8步:创建测试账户,客户端通过VIP连接数据库
↓
第9步:故障切换测试(停ha1、停db1,验证高可用)
🔧 3.3 实验一:7台机器基础配置(主机名+静态IP)
📋 实验目的
为每台机器设置固定的主机名和静态IP,确保集群内通信稳定,避免DHCP地址变动导致实验失败。
💡 运维作用
生产环境中所有服务器必须使用静态IP,动态IP会导致数据库连接中断、主从同步失败、LVS转发异常。
🔧 操作命令(逐行注释)
client2 配置
# ============================================================
# hostnamectl set-hostname:永久修改系统主机名,重启后永久生效
# 参数:client2.jhl.cloud 为新的主机名(FQDN格式)
# ============================================================
[root@localhost ~]# hostnamectl set-hostname client2.jhl.cloud
# ============================================================
# nmcli connection modify:修改网卡连接配置
# ens33:网卡设备名
# ipv4.method manual:关闭DHCP,启用手动静态IP模式
# ipv4.addresses 10.1.1.21/24:设置IPv4地址,/24表示24位子网掩码(255.255.255.0)
# ipv4.gateway 10.1.1.20:设置默认网关地址
# ipv4.dns 223.5.5.5:设置DNS服务器地址(阿里公共DNS)
# autoconnect yes:开机自动激活该网卡
# ============================================================
[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.1.21/24 ipv4.gateway 10.1.1.20 ipv4.dns 223.5.5.5 autoconnect yes
# ============================================================
# nmcli connection up:激活(重载)网卡连接,使配置立即生效,无需重启
# ============================================================
[root@localhost ~]# nmcli connection up ens33
client1 配置
[root@localhost ~]# hostnamectl set-hostname client1.jhl.cloud
[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.21/24 ipv4.gateway 10.1.8.20 ipv4.dns 223.5.5.5 autoconnect yes
[root@localhost ~]# nmcli connection up ens33
router 配置(双网卡)
# 修改主机名
[root@localhost ~]# hostnamectl set-hostname router.jhl.cloud
# 配置第一块网卡ens33(vmnet8,10.1.8.0/24网段)
[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.20/24 ipv4.gateway 10.1.8.2 ipv4.dns 223.5.5.5 autoconnect yes
[root@localhost ~]# nmcli connection up ens33
# ============================================================
# nmcli connection add:新增一个网卡连接配置
# type ethernet:连接类型为以太网
# con-name ens36:连接名称为ens36
# ifname ens36:物理网卡设备名为ens36
# ipv4.method manual:静态IP模式
# ipv4.addresses 10.1.1.20/24:第二块网卡IP(vmnet1网段)
# autoconnect yes:开机自动激活
# ============================================================
[root@localhost ~]# nmcli connection add type ethernet con-name ens36 ifname ens36 ipv4.method manual ipv4.addresses 10.1.1.20/24 autoconnect yes
[root@localhost ~]# nmcli connection up ens36
ha1 配置
[root@localhost ~]# hostnamectl set-hostname ha1.jhl.cloud
[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.13/24 ipv4.gateway 10.1.8.20 ipv4.dns 223.5.5.5 autoconnect yes
[root@localhost ~]# nmcli connection up ens33
ha2 配置
[root@localhost ~]# hostnamectl set-hostname ha2.jhl.cloud
[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.14/24 ipv4.gateway 10.1.8.20 ipv4.dns 223.5.5.5 autoconnect yes
[root@localhost ~]# nmcli connection up ens33
db1 配置
[root@localhost ~]# hostnamectl set-hostname db1.jhl.cloud
[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.11/24 ipv4.gateway 10.1.8.20 ipv4.dns 223.5.5.5 autoconnect yes
[root@localhost ~]# nmcli connection up ens33
db2 配置
[root@localhost ~]# hostnamectl set-hostname db2.jhl.cloud
[root@localhost ~]# nmcli connection modify ens33 ipv4.method manual ipv4.addresses 10.1.8.12/24 ipv4.gateway 10.1.8.20 ipv4.dns 223.5.5.5 autoconnect yes
[root@localhost ~]# nmcli connection up ens33
🔧 3.4 实验二:配置router路由器
📋 实验目的
让router成为两个网段(10.1.8.0/24 和 10.1.1.0/24)之间的网关,实现跨网段通信,并通过地址伪装(NAT)让内网机器访问外网。
💡 运维作用
模拟企业网络中的路由器/防火墙,实现多网段互通和外网访问。
🔧 操作命令(逐行注释)
# ============================================================
# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
# 向/etc/sysctl.conf追加内核参数,开启IPv4转发功能
# net.ipv4.ip_forward=1 表示允许内核转发不同网卡之间的数据包
# >> 表示追加写入(不覆盖原有内容)
# ============================================================
[root@router ~]# echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
# 或者使用sed命令替换(如果文件中已有ip_forward=0):
# sed -i "s/ip_forward=0/ip_forward=1/g" /etc/sysctl.conf
# ============================================================
# sysctl -p:从/etc/sysctl.conf加载内核参数,使配置立即生效
# -p 表示从默认配置文件加载
# ============================================================
[root@router ~]# sysctl -p
# ============================================================
# systemctl enable firewalld.service --now
# enable:设置firewalld开机自启
# --now:同时立即启动服务
# ============================================================
[root@router ~]# systemctl enable firewalld.service --now
# ============================================================
# firewall-cmd --set-default-zone=trusted
# 设置防火墙默认区域为trusted(信任区域),允许所有流量通过
# 实验环境简化操作,生产环境应严格配置规则
# ============================================================
[root@router ~]# firewall-cmd --set-default-zone=trusted
success
# ============================================================
# firewall-cmd --add-masquerade
# 临时开启地址伪装(SNAT),让内网机器通过router访问外网
# 不加--permanent为临时生效,重启防火墙后丢失
# ============================================================
[root@router ~]# firewall-cmd --add-masquerade
success
# ============================================================
# firewall-cmd --add-masquerade --permanent
# 永久开启地址伪装,写入配置文件,重启后不丢失
# ============================================================
[root@router ~]# firewall-cmd --add-masquerade --permanent
success
💾 第四部分:MariaDB安装与主主复制配置
🔧 4.1 实验三:db1安装与初始化MariaDB
📋 实验目的
在db1上安装MariaDB数据库,开启二进制日志(binlog),完成安全初始化,为后续主从复制做准备。
💡 运维作用
binlog是主从复制的数据源头,必须提前开启;安全初始化可以删除匿名用户、测试库,禁止root远程登录,提升数据库安全性。
🔧 操作命令(逐行注释)
步骤1:安装软件包
# ============================================================
# yum install -y mariadb-server
# yum在线安装MariaDB服务器软件包
# -y:自动确认所有交互提示,无需手动输入y
# mariadb-server:MariaDB数据库服务端主程序包
# ============================================================
[root@db1 ~]# yum install -y mariadb-server
步骤2:开启二进制日志
# ============================================================
# vim /etc/my.cnf.d/server.cnf
# 编辑MariaDB服务端配置文件
# 在[mysqld]块最后添加以下三行配置
# ============================================================
[root@db1 ~]# vim /etc/my.cnf.d/server.cnf
配置文件内容(在[mysqld]块末尾添加):
[mysqld]
# 在mysqld块最后添加如下内容
# ============================================================
# server-id=1:服务器唯一ID,主从架构中每台机器必须不同
# db1设为1,db2将设为2,用于标识binlog事件来源
# log_bin=mysql-bin:开启二进制日志,文件前缀为mysql-bin
# 生成的文件名为 mysql-bin.000001、mysql-bin.000002 ...
# relay_log=mysql-relay-bin:开启中继日志,文件前缀为mysql-relay-bin
# 作为从库时使用,存储从主库拉取的binlog内容
# ============================================================
server-id=1
log_bin=mysql-bin
relay_log=mysql-relay-bin
步骤3:启用并启动服务
# ============================================================
# systemctl enable mariadb --now
# enable:设置MariaDB开机自启
# --now:同时立即启动服务
# ============================================================
[root@db1 ~]# systemctl enable mariadb --now
步骤4:安全初始化
# ============================================================
# mysql_secure_installation
# MariaDB安全初始化脚本,交互式完成安全配置
# 包括:设置root密码、删除匿名用户、禁止root远程登录、删除test库、刷新权限
# ============================================================
[root@db1 ~]# mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.
# 输入当前root密码(刚安装默认为空,直接回车)
Enter current password for root (enter for none): `回车`
OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.
# 是否设置root密码?默认Y,直接回车
Set root password? [Y/n] `回车`
New password: `huawei`
Re-enter new password: `huawei`
Password updated successfully!
Reloading privilege tables..
... Success!
By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
# 是否删除匿名用户?默认Y,直接回车
Remove anonymous users? [Y/n] `回车`
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
# 是否禁止root远程登录?默认Y,直接回车
Disallow root login remotely? [Y/n] `回车`
... Success!
By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
# 是否删除test数据库及访问权限?默认Y,直接回车
Remove test database and access to it? [Y/n] `回车`
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
# 是否重新加载权限表?默认Y,直接回车
Reload privilege tables now? [Y/n] `回车`
... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Thanks for using MariaDB!
🔧 4.2 实验四:db2安装与初始化MariaDB
操作命令(与db1基本一致,仅server-id不同)
# 安装软件包
[root@db2 ~]# yum install -y mariadb-server
# 编辑配置文件,注意server-id=2(必须与db1不同!)
[root@db2 ~]# vim /etc/my.cnf.d/server.cnf
[mysqld]
# 在mysqld块最后添加如下内容
# server-id=2:db2的唯一ID,必须与db1的1不同
server-id=2
log_bin=mysql-bin
relay_log=mysql-relay-bin
# 启动服务
[root@db2 ~]# systemctl enable mariadb --now
# 安全初始化(密码同样设为huawei,操作步骤与db1完全一致)
[root@db2 ~]# mysql_secure_installation
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.
Enter current password for root (enter for none): `回车`
OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.
Set root password? [Y/n] `回车`
New password: `huawei`
Re-enter new password: `huawei`
Password updated successfully!
Reloading privilege tables..
... Success!
By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
Remove anonymous users? [Y/n] `回车`
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] `回车`
... Success!
By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] `回车`
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
Reload privilege tables now? [Y/n] `回车`
... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Thanks for using MariaDB!
🔧 4.3 实验五:第一组主从复制(db1主 → db2从)
📋 实验目的
配置db1为主库、db2为从库,实现db1的数据变更实时同步到db2。这是主主复制的 第一半。
💡 实验思路
- 在主库db1上创建专门用于复制的账号
repl,授权给从库db2的IP; - 查看主库当前binlog文件名和位置(position),这是从库同步的起点;
- 在从库db2上配置
change master to,指定主库地址、账号、binlog起点; - 启动从库同步线程(IO线程+SQL线程);
- 验证同步状态,两个线程都必须为Yes;
- 在主库写入测试数据,从库查询验证同步成功。
🔧 步骤1:配置主数据库db1
# ============================================================
# mysql -uroot -phuawei
# 以root用户登录MariaDB
# -u:指定用户名root
# -p:指定密码huawei(注意-p和密码之间没有空格)
# ============================================================
[root@db1 ~]# mysql -uroot -phuawei
# ============================================================
# grant replication slave, replication client on *.* to 'repl'@'10.1.8.12' identified by 'huawei';
# 创建复制账号并授权
# replication slave:允许该账号连接主库进行复制(必需权限)
# replication client:允许该账号查看主库状态(show master status)
# on *.*:对所有库所有表生效
# 'repl'@'10.1.8.12':用户名repl,只允许从10.1.8.12(db2)连接
# identified by 'huawei':设置密码为huawei
# ============================================================
MariaDB [(none)]> grant replication slave, replication client on *.* to 'repl'@'10.1.8.12' identified by 'huawei';
# ============================================================
# flush privileges;
# 刷新权限表,使刚才的授权立即生效
# ============================================================
MariaDB [(none)]> flush privileges;
# ============================================================
# show master status\G;
# 查看主库当前binlog状态
# \G:以垂直格式显示(每行一个字段,方便阅读)
# 关键信息:File(binlog文件名)、Position(位置)
# 这两个值要记录下来,配置从库时需要用到!
# ============================================================
MariaDB [(none)]> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000003
Position: 327
Binlog_Do_DB:
Binlog_Ignore_DB: mysql,information_schema,performance_schema
1 row in set (0.00 sec)
ERROR: No query specified
MariaDB [(none)]>
📌 记录关键信息:
- File:
mysql-bin.000003- Position:
327这两个值是从库同步的起点,配置从库时必须填入!
🔧 步骤2:配置从数据库db2
# 登录db2的MariaDB
[root@db2 ~]# mysql -uroot -phuawei
# ============================================================
# 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=327,
# master_connect_retry=30;
# 配置从库连接主库的参数(核心命令!)
# master_host:主库IP地址(db1的IP)
# master_user:复制账号用户名(repl)
# master_password:复制账号密码(huawei)
# master_port:主库端口(默认3306)
# master_log_file:从主库哪个binlog文件开始同步(刚才记录的mysql-bin.000003)
# master_log_pos:从binlog的哪个位置开始同步(刚才记录的327)
# master_connect_retry=30:连接失败后,每30秒重试一次
# ============================================================
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=327,
master_connect_retry=30;
Query OK, 0 rows affected (0.01 sec)
# ============================================================
# show slave status\G;
# 查看从库同步状态(启动前查看,IO和SQL线程都是No)
# ============================================================
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State:
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: 327
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: No
......
1 row in set (0.00 sec)
ERROR: No query specified
⚠️ 注意:此时
Slave_IO_Running: No和Slave_SQL_Running: No是正常的,因为还没启动同步线程!
🔧 步骤3:启动同步并验证状态
# ============================================================
# start slave;
# 启动从库的IO线程和SQL线程,开始同步
# ============================================================
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)
# 再次查看同步状态
MariaDB [(none)]> show slave status\G;
*************************** 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: 327
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 537
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
......
ERROR: No query specified
✅ 关键验证点:
Slave_IO_Running: Yes—— IO线程正常,正在等待主库发送事件Slave_SQL_Running: Yes—— SQL线程正常,正在重放relay log- 两个都必须是Yes,有一个为No就是同步失败!
🔧 步骤4:主库写入数据,从库验证同步
# 在主库db1上写入测试数据
[root@db1 ~]# mysql -uroot -phuawei
# 创建测试数据库
MariaDB [(none)]> create database test;
# 切换到test库
MariaDB [(none)]> use test;
# 创建linux表,两个字段:username和password
MariaDB [(none)]> create table linux(username varchar(15) not null,password varchar(15) not null);
# 插入3条测试数据
MariaDB [(none)]> insert into linux values ('jhl1', 'huawei');
MariaDB [(none)]> insert into linux values ('jhl2', 'huawei');
MariaDB [(none)]> insert into linux values ('jhl3', 'huawei');
# 提交事务(确保数据持久化)
MariaDB [(none)]> commit;
# 查询验证
MariaDB [(none)]> select * from linux;
# 在从库db2上查询,验证数据已同步
[root@db2 ~]# mysql -uroot -phuawei
MariaDB [(none)]> select * from test.linux;
+----------+----------+
| username | password |
+----------+----------+
| jhl1 | huawei |
| jhl2 | huawei |
| jhl3 | huawei |
+----------+----------+
3 rows in set (0.00 sec)
🎉 同步成功! 从库db2已经同步到了主库db1写入的3条数据!
🔧 4.4 实验六:第二组主从复制(db2主 → db1从)—— 形成主主复制
📋 实验目的
配置db2为主库、db1为从库,实现db2的数据变更实时同步到db1。这是主主复制的 第二半。
两组主从配置完成后,db1和db2互为主从,形成 主主复制(双主) 架构,两台都可以写入,数据双向同步。
💡 实验思路
- 在主库db2上创建复制账号
repl,授权给db1的IP; - 查看db2当前binlog文件名和位置;
- 在从库db1上配置
change master to master_host='10.1.8.12'; - 启动同步,验证两个线程为Yes;
- 在db2写入数据,db1查询验证。
🔧 步骤1:配置主数据库db2
# 登录db2
[root@db2 ~]# mysql -uroot -phuawei
# 创建复制账号,授权给db1(10.1.8.11)
MariaDB [(none)]> grant replication slave, replication client on *.* to 'repl'@'10.1.8.11' identified by 'huawei';
# 刷新权限
MariaDB [(none)]> flush privileges;
# 查看db2的binlog状态
MariaDB [(none)]> show master status\G;
*************************** 1. row ***************************
File: mysql-bin.000002
Position: 1769
Binlog_Do_DB:
Binlog_Ignore_DB: mysql,information_schema,performance_schema
1 row in set (0.00 sec)
ERROR: No query specified
📌 记录db2的关键信息:
- File:
mysql-bin.000002- Position:
1769
🔧 步骤2:配置从数据库db1
# 登录db1
[root@db1 ~]# mysql -uroot -phuawei
# 配置db1连接db2为主库(注意master_host是10.1.8.12!)
MariaDB [(none)]> change master to master_host='10.1.8.12',
master_user='repl',
master_password='huawei',
master_port=3306,
master_log_file='mysql-bin.000002',
master_log_pos=1769,
master_connect_retry=30;
Query OK, 0 rows affected (0.01 sec)
# 启动同步
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.01 sec)
# 查看同步状态
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.1.8.12
Master_User: repl
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 1769
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 537
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
......
ERROR: No query specified
✅ db1作为db2的从库,两个线程也都是Yes!主主复制架构搭建完成!
🔧 步骤3:验证双向同步
# 在db2上创建数据库jhl
MariaDB [(none)]> create database jhl;
Query OK, 1 row affected (0.00 sec)
# 在db1上查看,验证jhl库已同步过来
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| jhl |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)
🎉 双向同步成功! db2创建的jhl数据库已经同步到了db1!
至此,db1和db2形成了 主主复制 架构:
- db1写入 → 同步到db2 ✅
- db2写入 → 同步到db1 ✅
🌐 第五部分:LVS-DR模式配置
🤔 5.1 LVS-DR模式原理(先懂原理)
什么是LVS?
LVS(Linux Virtual Server)是Linux内核自带的 四层负载均衡器,工作在传输层,基于IP地址和端口转发请求,性能极高。
DR(直接路由)模式工作原理
客户端 → VIP请求 → LVS(DS) → 修改MAC地址 → 后端真实服务器(RS) → 直接响应客户端
| 角色 | 作用 |
|---|---|
| DS(Director Server) | LVS调度器,持有VIP,接收客户端请求,修改目标MAC地址转发给RS |
| RS(Real Server) | 后端真实服务器(db1/db2),处理请求后直接响应客户端(不经过LVS) |
| VIP | 虚拟IP,客户端访问的统一入口,DS和RS都要配置 |
DR模式的关键要求
- DS和RS必须在同一网段(因为是二层MAC转发);
- RS上必须配置VIP(在lo回环口或dummy网卡上),用于响应目标IP为VIP的数据包;
- RS必须抑制ARP响应(否则VIP会冲突,多个机器响应ARP导致混乱);
- 响应数据包直接从RS发给客户端,不经过DS,所以LVS不会成为带宽瓶颈。
🔧 5.2 实验七:配置LVS-RS(db1和db2都要做)
📋 实验目的
在两台数据库服务器(db1、db2)上配置dummy虚拟网卡绑定VIP,并设置ARP抑制参数,使其能作为LVS-DR模式的后端真实服务器(RS)。
💡 为什么要这么做?
- dummy网卡绑定VIP:让RS能接收目标IP为VIP的数据包(LVS转发过来的请求);
- ARP抑制:防止RS在物理网卡上响应VIP的ARP请求,避免VIP冲突(只有DS应该响应VIP的ARP)。
🔧 操作命令(db1和db2执行完全相同的配置)
步骤1:增加虚拟网卡(dummy)
# ============================================================
# nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32
# 创建一个dummy类型的虚拟网卡并配置IP
# type dummy:设备类型为dummy(虚拟网卡,不依赖物理硬件)
# ifname dummy:接口名称为dummy
# con-name dummy:连接名称为dummy
# ipv4.method manual:静态IP模式
# ipv4.addresses 10.1.8.100/32:配置VIP地址,/32表示32位掩码(单主机地址)
# 为什么用/32?因为VIP只需要在本地存在,不需要网段路由,/32避免产生网段路由
# ============================================================
[root@db1 ~]# nmcli connection add type dummy ifname dummy con-name dummy ipv4.method manual ipv4.addresses 10.1.8.100/32
# ============================================================
# nmcli connection up dummy
# 激活dummy虚拟网卡,使VIP配置生效
# ============================================================
[root@db1 ~]# nmcli connection up dummy
⚠️ db2上执行完全相同的命令!
步骤2:配置ARP参数(抑制ARP响应)
# ============================================================
# cat >> /etc/sysctl.conf << EOF
# 向/etc/sysctl.conf追加内核ARP参数(Here Document方式)
# >> 追加写入,EOF为结束标记
# ============================================================
[root@db1-2 ~]# cat >> /etc/sysctl.conf << EOF
# ============================================================
# net.ipv4.conf.all.arp_ignore = 1
# 所有网卡的ARP响应级别设为1
# 级别1:只在目标IP是本机网卡本地地址时才响应ARP请求
# 作用:物理网卡ens33不会响应VIP的ARP请求(因为VIP在dummy上)
#
# net.ipv4.conf.all.arp_announce = 2
# 所有网卡的ARP宣告级别设为2
# 级别2:始终使用最佳本地地址作为ARP宣告的源IP
# 作用:避免使用VIP作为ARP宣告源,防止VIP泄露
#
# net.ipv4.conf.dummy.arp_ignore = 1
# dummy网卡的ARP响应级别设为1
# net.ipv4.conf.dummy.arp_announce = 2
# dummy网卡的ARP宣告级别设为2
# ============================================================
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
# ============================================================
# sysctl -p:加载sysctl.conf中的内核参数,使ARP配置立即生效
# ============================================================
[root@db1-2 ~]# sysctl -p
⚠️ db2上执行完全相同的命令!
🔥 第六部分:Keepalived + LVS-DS配置
🤔 6.1 Keepalived与LVS的关系
Keepalived不仅提供VRRP高可用(VIP漂移),还内置了LVS配置管理和后端健康检查功能:
| 功能 | 说明 |
|---|---|
| VRRP实例 | 管理VIP,主备节点心跳,故障自动漂移 |
| virtual_server | 定义LVS虚拟服务(VIP+端口) |
| real_server | 定义后端真实服务器(IP+端口) |
| TCP_CHECK | 健康检查,检测后端端口是否存活,故障自动剔除 |
🔧 6.2 实验八:配置ha1(LVS主节点 + Keepalived Master)
📋 实验目的
在ha1上安装Keepalived和ipvsadm,配置为主节点(MASTER,优先级110),持有VIP,配置LVS-DR转发规则和后端健康检查。
💡 实验思路
- 安装keepalived(提供VRRP和LVS管理)和ipvsadm(LVS管理工具);
- 备份原始配置文件(防止改错无法恢复);
- 编写keepalived.conf:
- global_defs:设置router_id;
- vrrp_instance:VRRP实例,state MASTER,priority 110,VIP 10.1.8.100;
- virtual_server:LVS虚拟服务,VIP:3306,DR模式,轮询算法;
- real_server:两个后端db1和db2,TCP健康检查。
- 启动服务。
🔧 操作命令(逐行注释)
# ============================================================
# yum install -y keepalived ipvsadm
# 安装Keepalived和ipvsadm
# keepalived:高可用软件,提供VRRP协议和LVS配置管理
# ipvsadm:LVS规则管理工具,可手动查看和管理IPVS规则
# ============================================================
[root@ha1 ~]# yum install -y keepalived ipvsadm
# ============================================================
# cp /etc/keepalived/keepalived.conf{,.bak}
# 备份原始配置文件
# {,.bak} 是bash的大括号扩展,等价于:
# cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak
# ============================================================
[root@ha1 ~]# cp /etc/keepalived/keepalived.conf{,.bak}
# ============================================================
# vim /etc/keepalived/keepalived.conf
# 编辑Keepalived主配置文件
# ============================================================
[root@ha1 ~]# vim /etc/keepalived/keepalived.conf
完整配置文件(逐行逐字段注释)
! Configuration File for keepalived
# ============================================================
# global_defs:全局定义段
# ============================================================
global_defs {
router_id ha1
# router_id:路由器ID,本机在VRRP集群中的唯一标识,主备必须不同
}
# ============================================================
# vrrp_instance db:VRRP实例定义,实例名称为db
# ============================================================
vrrp_instance db {
state MASTER
# state:初始状态,MASTER为主节点,BACKUP为备节点
# 注意:最终主备由priority决定,state只是初始状态
interface ens33
# interface:VRRP心跳和VIP绑定的物理网卡
virtual_router_id 51
# virtual_router_id:虚拟路由器ID(VRID),范围1-255
# 同一VRRP集群的所有节点必须相同!不同集群用不同ID避免冲突
priority 110
# priority:优先级,范围1-254,数值越大越优先成为Master
# ha1设110,ha2设100,所以ha1优先为主
advert_int 1
# advert_int:VRRP心跳通告间隔,单位秒,默认1秒
# Master每秒发送一次心跳,Backup收不到心跳就会抢占
authentication {
# authentication:VRRP认证配置,防止非法节点加入集群
auth_type PASS
# auth_type:认证类型,PASS为明文密码认证
auth_pass jhl@123
# auth_pass:认证密码,最多8位有效字符,所有节点必须完全相同
}
virtual_ipaddress {
# virtual_ipaddress:虚拟IP地址(VIP)列表
10.1.8.100/24
# VIP地址,/24掩码,客户端访问数据库的统一入口
}
}
# ============================================================
# virtual_server 10.1.8.100 3306:LVS虚拟服务定义
# VIP为10.1.8.100,端口3306(MySQL/MariaDB默认端口)
# ============================================================
virtual_server 10.1.8.100 3306 {
delay_loop 6
# delay_loop:健康检查间隔,每6秒检查一次后端服务器状态
lb_algo rr
# lb_algo:负载均衡调度算法
# rr:轮询(Round Robin),依次将请求分发给后端服务器
# 其他算法:wrr加权轮询、lc最少连接、wlc加权最少连接等
lb_kind DR
# lb_kind:LVS工作模式
# DR:直接路由模式(Direct Routing),响应不经过LVS,性能最高
# 其他模式:NAT(网络地址转换)、TUN(IP隧道)
persistence_timeout 50
# persistence_timeout:持久化超时时间,单位秒
# 同一客户端在50秒内的连接会被分发到同一台后端服务器
# 数据库场景建议开启,避免同一事务被分到不同节点
protocol TCP
# protocol:转发协议,TCP或UDP,数据库用TCP
# ============================================================
# real_server 10.1.8.11 3306:后端真实服务器1(db1)
# ============================================================
real_server 10.1.8.11 3306 {
weight 1
# weight:权重,权重越大分到的请求越多
# rr算法下权重相同则平均分配
TCP_CHECK {
# TCP_CHECK:TCP端口健康检查
connect_timeout 3
# connect_timeout:连接超时时间,3秒连不上判定为故障
retry 3
# retry:重试次数,连续3次失败才判定节点故障
delay_before_retry 3
# delay_before_retry:每次重试之间的间隔,3秒
}
}
# ============================================================
# real_server 10.1.8.12 3306:后端真实服务器2(db2)
# ============================================================
real_server 10.1.8.12 3306 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
⚠️ 重要说明:在Keepalived+LVS配置中,后端
real_server不支持直接使用域名,必须指定IP地址。原因:
- LVS工作在四层(传输层),基于IP和端口转发,不涉及DNS解析,无法识别域名;
- Keepalived配置解析器不支持域名格式,会直接视为无效配置;
- 若强行填写域名,启动时会报错
invalid IP address,导致配置加载失败。替代方案:通过脚本动态更新配置。
# ============================================================
# systemctl enable keepalived.service --now
# 设置Keepalived开机自启,并立即启动服务
# ============================================================
[root@ha1 ~]# systemctl enable keepalived.service --now
🔧 6.3 实验九:配置ha2(LVS备节点 + Keepalived Backup)
📋 实验目的
在ha2上配置为备节点(BACKUP,优先级100),当ha1故障时自动接管VIP。
🔧 操作命令
# 安装软件
[root@ha2 ~]# yum install -y keepalived ipvsadm
# 备份配置
[root@ha2 ~]# cp /etc/keepalived/keepalived.conf{,.bak}
# 编辑配置
[root@ha2 ~]# vim /etc/keepalived/keepalived.conf
ha2完整配置文件
! Configuration File for keepalived
global_defs {
router_id ha2
# 注意:router_id为ha2,与ha1不同
}
vrrp_instance db {
state BACKUP
# state:BACKUP备节点
interface ens33
virtual_router_id 51
# VRID必须与ha1相同(51)!
priority 100
# 优先级100,低于ha1的110,所以正常情况下ha1为主
advert_int 1
authentication {
auth_type PASS
auth_pass jhl@123
# 密码必须与ha1完全相同!
}
virtual_ipaddress {
10.1.8.100/24
# VIP必须与ha1相同!
}
}
virtual_server 10.1.8.100 3306 {
delay_loop 6
lb_algo rr
lb_kind DR
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 2
# 注意:ha2中db2的权重设为2(与ha1配置略有不同,演示加权效果)
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
# 启动服务
[root@ha2 ~]# systemctl enable keepalived.service --now
🧪 第七部分:综合测试与故障验证
🔧 7.1 实验十:创建测试账户并通过VIP连接
📋 实验目的
在数据库上创建一个允许远程连接的测试账户,然后从客户端通过VIP(10.1.8.100)连接数据库,验证LVS负载均衡是否正常工作。
🔧 步骤1:在db1上创建测试账户
# 登录db1
[root@db1 ~]# mysql -uroot -p
# ============================================================
# grant ALL PRIVILEGES on *.* to 'jhl'@'%' identified by 'huawei';
# 创建远程连接用户并授权
# ALL PRIVILEGES:所有权限(生产环境应按需最小授权)
# on *.*:所有库所有表
# 'jhl'@'%':用户名jhl,%表示允许从任意IP连接
# identified by 'huawei':密码huawei
# ============================================================
MariaDB [(none)]> grant ALL PRIVILEGES on *.* to 'jhl'@'%' identified by 'huawei';
# 刷新权限
MariaDB [(none)]> FLUSH PRIVILEGES;
# 退出
MariaDB [(none)]> quit
Bye
🔧 步骤2:客户端安装MySQL客户端并通过VIP连接
# ============================================================
# yum install -y mysql
# 安装MySQL客户端工具(不是服务端,只是mysql命令行客户端)
# ============================================================
[root@client1 ~]# yum install -y mysql
# ============================================================
# mysql -ujhl -phuawei -h 10.1.8.100
# 通过VIP连接数据库
# -u jhl:用户名jhl
# -p huawei:密码huawei
# -h 10.1.8.100:主机地址为VIP(LVS统一入口)
# ============================================================
[root@client1 ~]# mysql -ujhl -phuawei -h 10.1.8.100
✅ 如果能成功进入MariaDB命令行,说明:
- Keepalived的VIP正常工作;
- LVS-DR转发正常;
- 后端MariaDB服务正常;
- 主主复制数据一致。
🔧 7.2 实验十一:LVS节点故障切换测试(停止ha1的Keepalived)
📋 实验目的
模拟LVS主节点ha1故障,验证VIP是否自动漂移到ha2,客户端是否仍能正常连接数据库。
🔧 操作命令
# ============================================================
# systemctl stop keepalived.service
# 停止ha1上的Keepalived服务,模拟主节点故障
# 停止后ha1不再发送VRRP心跳,ha2收不到心跳会自动升级为Master并接管VIP
# ============================================================
[root@ha1 ~]# systemctl stop keepalived.service
📊 实验现象解释
- ha1停止Keepalived后:ha1释放VIP 10.1.8.100,不再发送VRRP心跳;
- ha2检测到心跳丢失:ha2等待
3 × advert_int = 3秒后,判定Master故障,自动升级为Master; - VIP漂移:ha2发送ARP广播,宣告VIP 10.1.8.100的MAC地址已变更为ha2的MAC;
- 客户端无感知:客户端的ARP缓存更新后,请求继续发往VIP,现在由ha2进行LVS转发;
- 业务不中断:数据库连接保持正常(因为persistence_timeout和TCP长连接)。
# 在ha2上查看VIP是否已漂移过来
[root@ha2 ~]# ip addr show ens33 | grep 10.1.8.100
# 应该能看到10.1.8.100/24已绑定到ha2的ens33网卡
# 客户端再次通过VIP连接,验证仍然正常
[root@client1 ~]# mysql -ujhl -phuawei -h 10.1.8.100
# 连接成功!说明VIP漂移后业务不受影响
# ============================================================
# systemctl start keepalived.service
# 恢复ha1的Keepalived服务
# 因为ha1优先级110 > ha2优先级100,ha1启动后会重新抢占VIP(抢占模式)
# ============================================================
[root@ha1 ~]# systemctl start keepalived.service
📊 恢复后的现象
- ha1启动Keepalived后,因为优先级更高(110 > 100),会发送更高优先级的VRRP通告;
- ha2收到更高优先级的通告后,自动降级为Backup,释放VIP;
- VIP漂移回ha1,客户端继续无感知访问。
🔧 7.3 实验十二:数据库节点故障测试(停止db1的MariaDB)
📋 实验目的
模拟后端数据库节点db1故障,验证LVS的健康检查是否能自动剔除故障节点,将请求全部转发到健康的db2。
🔧 操作命令
# ============================================================
# systemctl stop mariadb
# 停止db1上的MariaDB服务,模拟数据库节点故障
# ============================================================
[root@db1 ~]# systemctl stop mariadb
📊 实验现象解释
- db1的MariaDB停止后:3306端口不再监听;
- Keepalived的TCP_CHECK检测:每6秒检查一次,连续3次(共约18秒)连接超时后,判定db1故障;
- 自动剔除故障节点:LVS将db1从转发列表中移除,所有请求只转发给db2;
- 客户端无感知:新的数据库连接自动落到db2,业务不中断;
- 主主复制保障:因为db1和db2是主主复制,db2上有完整数据,写入db2的数据在db1恢复后会同步回去。
# 在ha1上查看LVS转发规则,确认db1已被剔除
[root@ha1 ~]# ipvsadm -Ln
# 正常情况下能看到两个real_server,故障后只能看到db2(10.1.8.12)
# 客户端通过VIP连接,验证仍然正常(请求被转发到db2)
[root@client1 ~]# mysql -ujhl -phuawei -h 10.1.8.100
# 连接成功!说明LVS健康检查自动剔除了故障节点
🐛 第八部分:常见故障排查指南
🚨 8.1 高频故障对照表
| 故障现象 | 可能原因 | 排查命令/解决方案 |
|---|---|---|
| 主从同步IO线程为No | 网络不通、账号密码错误、binlog文件/位置错误 | ping 主库IP、检查repl账号权限、核对master_log_file和pos |
| 主从同步SQL线程为No | 主键冲突、数据不一致、SQL执行错误 | 查看 show slave status\G 中的Last_SQL_Error,跳过错误或重新同步 |
| VIP无法ping通 | Keepalived未启动、VRID/密码不一致、防火墙拦截VRRP | systemctl status keepalived、检查配置、firewall-cmd --add-protocol=vrrp |
| LVS转发失败 | RS未配置VIP、ARP未抑制、DR模式要求同网段 | 检查dummy网卡VIP、sysctl -a | grep arp_ignore、确认DS和RS同网段 |
| 客户端连接VIP超时 | 后端数据库未启动、健康检查未通过、防火墙拦截3306 | ipvsadm -Ln 查看RS状态、检查MariaDB服务、放行3306端口 |
| 脑裂(双主都有VIP) | 心跳链路中断、VRID不一致、认证密码不同 | 检查VRRP通信、统一VRID和密码、排查网络连通性 |
🔧 8.2 核心排查命令
# 查看Keepalived运行状态
systemctl status keepalived
# 查看Keepalived日志(定位VRRP切换、健康检查故障)
tail -f /var/log/messages | grep Keepalived
# 查看LVS当前转发规则和连接数
ipvsadm -Ln
ipvsadm -Lnc # 查看连接表
# 查看VIP绑定情况
ip addr show ens33 | grep 10.1.8.100
# 查看MariaDB主从同步状态
mysql -uroot -phuawei -e "show slave status\G" | grep Running
# 测试后端数据库端口连通性
telnet 10.1.8.11 3306
📝 文末总结
🎯 核心知识点回顾
| 模块 | 核心要点 |
|---|---|
| MariaDB主主复制 | 两组主从反向配置,server-id必须不同,binlog双向同步,IO/SQL线程都要Yes |
| LVS-DR模式 | DS和RS同网段,RS配置dummy网卡绑VIP+ARP抑制,响应直接返回客户端不经过LVS |
| Keepalived高可用 | VRRP协议管理VIP,priority决定主备,TCP_CHECK健康检查自动剔除故障节点 |
| real_server限制 | 必须用IP地址,不能用域名,LVS工作在四层不做DNS解析 |
| 故障切换 | LVS节点故障→VIP秒级漂移;数据库节点故障→健康检查自动剔除,请求转健康节点 |
💡 生产环境最佳实践
- server-id全局唯一:主主架构中每台数据库的server-id必须不同,否则binlog同步混乱;
- 自增ID偏移:主主复制生产环境建议配置
auto_increment_increment=2和auto_increment_offset,避免双主同时写入主键冲突; - 健康检查阈值:根据业务容忍度调整
connect_timeout、retry、delay_before_retry; - 持久化连接:数据库场景建议开启
persistence_timeout,避免同一事务分到不同节点; - 监控告警:对Keepalived状态、LVS RS状态、MariaDB主从同步状态做监控告警。
💬 互动话题
你们公司的数据库高可用用的是什么方案?MariaDB主主 + LVS 还是 MHA / Orchestrator?
搭建过程中踩过什么坑?欢迎在评论区交流~如果这篇文章对你有帮助,别忘了 点赞👍 收藏⭐ 关注👀 三连支持!
我们下篇文章见~拜拜!👋
更多推荐




所有评论(0)