Linux高可用与负载均衡技术栈指南

1. MySQL 主从复制

1.1 复制核心原理

MySQL 主从复制基于**二进制日志(binlog)**实现数据同步,涉及三个核心线程:

线程 所在节点 作用
Binlog Dump Thread 主库 将主库的 binlog 事件发送给从库
I/O Thread 从库 连接到主库,请求 binlog 并写入中继日志
SQL Thread 从库 从中继日志读取事件,在从库上重放执行

工作流程:主库将所有数据修改操作记录到二进制日志;从库 I/O 线程通过 TCP 连接获取主库的 binlog 并存储为中继日志(Relay Log);从库 SQL 线程解析中继日志中的事件,在本地数据库重现相同操作。

复制模式:MySQL 支持异步(默认)、半同步、全同步三种模式,实际生产中半同步复制应用最广,在性能和数据一致性之间取得较好平衡。

1.2 一主一从配置实战

一、环境准备

角色 IP 地址 系统环境 MySQL 版本
主库 Master 192.168.1.10 Rocky9 MySQL 8.0
从库 Slave 192.168.1.11 Rocky9 MySQL 8.0

检查清单:主从节点 MySQL 版本一致;3306 端口网络互通;服务器时间通过 NTP 同步。

二、主库配置

编辑 /etc/my.cnf

ini 复制代码
[mysqld]
server-id = 1                           # 唯一标识符,集群内不可重复
log-bin = mysql-bin                     # 启用二进制日志
binlog-format = ROW                     # 推荐使用 ROW 格式,保证数据一致性
sync-binlog = 1                         # 每次事务提交都同步到磁盘
expire-logs-days = 7                    # 自动清理 7 天前的日志
binlog-row-image = FULL                 # 完整行镜像

参数说明:server-id 在整个复制集群中必须唯一;log-bin 指定二进制日志文件名前缀;binlog-format=ROW 记录每行的变更,数据一致性最高;sync-binlog=1 保证 binlog 可靠性。重启 MySQL:systemctl restart mysqld

三、创建复制账号

登录主库 MySQL:

sql 复制代码
CREATE USER 'repl'@'%' IDENTIFIED BY 'StrongPass@123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

查看当前二进制日志位点:

sql 复制代码
SHOW MASTER STATUS;
-- 记录 File 和 Position 值,例如 mysql-bin.000001 和 154

四、从库配置

编辑 /etc/my.cnf

ini 复制代码
[mysqld]
server-id = 2                           # 从库唯一 ID,不能与主库重复
relay-log = mysql-relay-bin             # 中继日志
read-only = 1                           # 建议开启只读模式防止误操作

参数说明:从库必须设置与主库不同的 server-idrelay-log 指定中继日志位置;read-only=1 防止在从库误执行写操作。重启 MySQL:systemctl restart mysqld

登录从库 MySQL,配置主库信息:

sql 复制代码
CHANGE MASTER TO
    MASTER_HOST = '192.168.1.10',
    MASTER_USER = 'repl',
    MASTER_PASSWORD = 'StrongPass@123',
    MASTER_LOG_FILE = 'mysql-bin.000001',
    MASTER_LOG_POS = 154;

START SLAVE;

验证复制状态:

sql 复制代码
SHOW SLAVE STATUS\G
-- 检查 Slave_IO_Running 和 Slave_SQL_Running 是否为 Yes

1.3 一主多从配置实战

一主多从架构在标准一主一从的基础上,可通过增加从库节点实现读能力的线性扩展。适用于读多写少、数据安全性要求较高的场景,将读流量分散到多个从库,分担主库查询压力。常见搭配方案包括"一主多从 + 读写分离",配合中间件(如 MyCat、ProxySQL)或 Keepalived 提供故障切换与统一接入。

核心实现:在多个从库节点上重复执行"一主一从"的从库配置步骤即可。 具体操作如下:

环境准备:

角色 IP 地址 MySQL 版本 server-id
Master 192.168.1.10 MySQL 8.0 1
Slave1 192.168.1.11 MySQL 8.0 2
Slave2 192.168.1.12 MySQL 8.0 3

步骤一:主库配置(与一主一从相同)

已配置好 master,且已创建 repl 账号(binlog 位点已知)。

步骤二:从库1配置(192.168.1.11)

在 Slave1 上配置 /etc/my.cnf,设置 server-id=2 并启用 read-only=1。重启服务后执行:

sql 复制代码
CHANGE MASTER TO
    MASTER_HOST = '192.168.1.10',
    MASTER_USER = 'repl',
    MASTER_PASSWORD = 'StrongPass@123',
    MASTER_LOG_FILE = 'mysql-bin.000001',
    MASTER_LOG_POS = 154;

START SLAVE;
SHOW SLAVE STATUS\G   -- 验证 Slave_IO_Running 和 Slave_SQL_Running 是否为 Yes

步骤三:从库2配置(192.168.1.12)

在 Slave2 上配置 /etc/my.cnf,设置 server-id=3 并启用 read-only=1。重启服务后执行:

sql 复制代码
CHANGE MASTER TO
    MASTER_HOST = '192.168.1.10',
    MASTER_USER = 'repl',
    MASTER_PASSWORD = 'StrongPass@123',
    MASTER_LOG_FILE = 'mysql-bin.000001',
    MASTER_LOG_POS = 154;

START SLAVE;
SHOW SLAVE STATUS\G   -- 验证复制状态

验证: 在主库创建新表或插入数据,检查 Slave1 和 Slave2 是否都能同步该数据。

1.4 级联复制配置实战

级联复制通过一个中间从库(级联服务器)同时作为主库的下级和下级从库的主库,适用于需要为特定从库或应用隔离主库变更影响的场景,例如让某个下游系统从级联服务器同步数据,而不直接连接主库。

拓扑结构: Master → Master-Slave(级联节点)→ Slave

环境准备:

角色 IP 地址 server-id
Master 192.168.1.10 1
Master-Slave(级联节点) 192.168.1.11 2(开启 log-bin 和 log-slave-updates)
Slave 192.168.1.12 3

步骤一:主库配置(192.168.1.10)

与一主一从配置相同:

ini 复制代码
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW

创建 repl 账号,记录位点。

步骤二:级联节点配置(192.168.1.11)

编辑 /etc/my.cnf,关键是要开启 log-binlog-slave-updates

ini 复制代码
[mysqld]
server-id = 2                           # 级联节点的唯一 ID
log-bin = mysql-bin                     # 必须开启 binlog
log-slave-updates = 1                   # 关键:将从主库同步的数据也写入本机的 binlog
read-only = 1
relay-log = mysql-relay-bin

log-slave-updates 的作用:让级联节点在应用主库的变更后,也将这些变更写入自己的 binlog,这样下级从库才能从级联节点上同步数据。重启 MySQL 后,将级联节点配置为 Master 的从库(与一主一从相同)。

步骤三:下级从库配置(192.168.1.12)

编辑 /etc/my.cnf

ini 复制代码
[mysqld]
server-id = 3
read-only = 1

重启 MySQL 后,将下级从库指向级联节点(192.168.1.11),而非直接指向主库:

sql 复制代码
CHANGE MASTER TO
    MASTER_HOST = '192.168.1.11',
    MASTER_USER = 'repl',
    MASTER_PASSWORD = 'StrongPass@123',
    MASTER_LOG_FILE = 'mysql-bin.000001',
    MASTER_LOG_POS = 154;

START SLAVE;

验证流程:

  1. 在主库(192.168.1.10)创建新表或插入数据
  2. 查看级联节点(192.168.1.11),数据应已同步
  3. 查看下级从库(192.168.1.12),数据也应已同步

常见问题 :复制中断可使用 STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE; 跳过错误事件;延迟问题可通过启用并行复制(slave_parallel_workers=8)优化。


2. LVS 概述

2.1 LVS 概念

LVS(Linux Virtual Server,Linux 虚拟服务器)是由章文嵩博士于 1998 年开发的开源负载均衡解决方案,现已集成至 Linux 内核(通过 IPVS 模块实现),可在传输层(TCP/UDP)进行高性能流量分发。

核心架构由三部分组成:

  • 负载调度器(Director):接收客户端请求的入口节点,运行 ipvs 服务
  • 服务器池(Real Server,RS):实际处理请求的应用服务器集群
  • 共享存储(可选):确保 RS 间数据一致性

LVS 工作在内核层,直接处理 IP 数据包,具有高性能、低延迟、高并发等优势。相比 Nginx、HAProxy 等应用层负载均衡器,LVS 不解析应用层协议,省去了用户态与内核态的切换开销,吞吐量可达 10Gbps+ 级别。

2.2 LVS 工作原理

终端用户访问 LVS 调度器的虚拟 IP(VIP),调度器根据预设的调度算法将请求分发至后端真实服务器(RS),所有 RS 提供一致的服务,整个集群对用户完全透明。

在数据包层面,LVS 通过修改 IP 层或链路层信息实现请求转发,根据不同的工作模式采用不同的包处理方式。

2.3 LVS 集群模式特性

LVS 的核心工作模式有三种:

模式 转发原理 拓扑要求 性能 适用场景
NAT 模式 修改数据包的目标 IP 地址 RS 可使用私有 IP;LVS 做网关 中等,LVS 需处理进出双向流量 内网环境、测试环境
DR 模式 修改 MAC 地址 RS 与 LVS 同网段;RS 需配置 VIP 最高,LVS 仅处理入向请求 高并发、低延迟业务(电商、游戏等)
TUN 模式 IP-in-IP 隧道封装 RS 可跨网段部署 较高 跨地域/跨机房部署

NAT 模式:LVS 作为网关,通过修改数据包的源/目的 IP 实现转发,支持异构操作系统,无需修改 RS 配置,但所有流量需经 LVS 转发,扩展性受限。

DR 模式:LVS 与 RS 共享 VIP,通过修改 MAC 地址将请求直接路由至目标服务器,响应包绕过 LVS 直接返回客户端。需在 RS 上配置 arp_ignore=1 和 arp_announce=2 避免 ARP 冲突。DR 模式性能最优,适合金融、电商等高并发场景。

TUN 模式:LVS 将原始 IP 包封装在新的 IP 包中转发至后端服务器,RS 解封装后处理请求并直接响应客户端,适用于跨机房或广域网部署。


3. LVS 调度算法

LVS 的调度算法可分为静态调度 (基于预设规则)和动态调度(基于实时状态)两大类,共提供十种调度算法。

3.1 静态调度算法

算法 原理 适用场景
RR(轮询) 按顺序将请求依次分配给每台 RS,循环往复 服务器性能相近的同构集群
WRR(加权轮询) 为每台 RS 分配权重,权重高的接收更多请求 服务器性能存在差异的异构集群
DH(目标地址哈希) 基于目标 IP 的哈希值将请求定向到固定 RS 内网服务定向,实现会话保持
SH(源地址哈希) 基于源 IP 的哈希值分配请求 企业内网多数据中心架构

RR 实现最简单,轮询分配负载,数学表达为:第 i 个请求分配至服务器 S_{(i mod n)+1}。

WRR 为性能更强的服务器分配更高权重,权重高的服务器获得更多请求。例如将核心服务器权重设为 3,普通服务器权重设为 1。

SH/DH 基于哈希将请求持久化绑定到特定服务器,适用于需要会话保持的场景,但服务器故障时会产生大量迁移。

3.2 动态调度算法

算法 原理 适用场景
LC(最少连接) 将新请求分配给当前活动连接数最少的 RS 长连接服务
WLC(加权最少连接) 结合权重与连接数,分配至连接数/权重比值最小的 RS 异构集群中的长连接业务
SED(最短期望延迟) 基于 WLC 的改进,加入权重计算 需要平衡延迟的场景
NQ(永不排队) SED 的变种,优先分配空闲服务器 空闲服务器较多的场景
LBLC(基于局部性的最少连接) 基于目标 IP 的最小连接,优先连接缓存命中目标 缓存集群

LC 将新请求分配至连接数最少的服务器,数学表达为:分配至 min(conn_count[i]) 的服务器。

WLC 在 LC 基础上加入权重计算:分配至 min(conn_count[i]/weight[i]) 的服务器。

3.3 算法选型建议

业务类型 推荐算法 原因
长连接服务 WLC / SH 动态感知负载或保持会话连续性
短连接服务 RR / WRR 简单高效,无需维护连接状态
异构集群 WRR / WLC 根据性能差异分配负载
会话保持要求 SH / DH 哈希绑定用户到固定服务器

4. LVS 配置文件详解

4.1 keepalived 配置文件结构

keepalived 的配置文件 /etc/keepalived/keepalived.conf 由多个配置块组成,每个块用 {} 界定。主要包含三大模块:

1. 全局定义块(global_defs)

conf 复制代码
global_defs {
    router_id LVS_DIRECTOR          # 节点唯一标识,备机应改为不同的标识
    lvs_id LVS_LOAD_BALANCER        # LVS 标识
    enable_script_security          # 启用脚本安全检查
}

2. VRRP 实例配置块(vrrp_instance)

负责 VIP 的漂移管理,是 Keepalived 实现高可用的核心:

conf 复制代码
vrrp_instance VI_1 {
    state MASTER                    # 节点角色:MASTER(主)或 BACKUP(备)
    interface eth0                  # 绑定网卡接口
    virtual_router_id 51            # 虚拟路由 ID,主备必须一致(范围 0-255)
    priority 150                    # 优先级,值越高越优先(MASTER 应高于 BACKUP)
    advert_int 1                    # VRRP 心跳广播间隔(秒),越小切换越快
    
    authentication {
        auth_type PASS              # 认证类型:PASS(简单密码)或 AH
        auth_pass 123456            # 认证密码,主备必须一致
    }
    
    virtual_ipaddress {
        192.168.10.100/24 dev eth0 label eth0:1   # 浮动 VIP 及网卡别名
    }
}
  • virtual_router_id:主备节点必须保持一致,用于区分不同的 VRRP 实例
  • priority:MASTER 节点应配置更高优先级,如 150,BACKUP 为 100
  • advert_int:心跳周期,值越小故障切换越快,但网络开销越大

3. 虚拟服务器配置块(virtual_server)

该模块是 Keepalived 与 LVS 深度整合的核心,所有 ipvsadm 命令功能均可通过此模块配置:

conf 复制代码
virtual_server 192.168.10.100 80 {   # VIP 和端口
    delay_loop 6                     # 健康检查间隔(秒)
    lb_algo wrr                      # 负载均衡算法:rr/wrr/lc/wlc/lblc/sh/dh
    lb_kind DR                       # 工作模式:NAT(-m)/ DR(-g)/ TUN(-i)
    persistence_timeout 60           # 会话保持时间(秒)
    protocol TCP                     # 协议类型:TCP 或 UDP
    
    # Real Server 1 定义
    real_server 10.0.0.11 80 {
        weight 1                     # RS 权重,值越高分配越多请求
        inhibit_on_failure           # 故障时标记为不可用
        TCP_CHECK {                  # TCP 健康检查方式
            connect_timeout 3        # 连接超时(秒)
            nb_get_retry 3           # 重试次数
            delay_before_retry 2     # 重试前延迟(秒)
            connect_port 80          # 检查的目标端口
        }
    }
    
    # Real Server 2 定义
    real_server 10.0.0.12 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 2
            connect_port 80
        }
    }
}

关键参数说明

  • lb_algo:支持算法包括 rr(轮询)、wrr(加权轮询)、lc(最少连接)、wlc(加权最少连接)、lblc、sh(源哈希)、dh(目标哈希)
  • persistence_timeout:设置后将同一源 IP 的请求始终转发到同一 RS,避免会话状态丢失
  • health check:Keepalived 通过 MISC_CHECK、TCP_CHECK、HTTP_GET 等方式检测 RS 健康状态,自动剔除故障节点
  • weight:结合 lb_algo 为 wrr/wlc 使用,权重越高分配越多请求

5. LVS 部署实战

5.1 NAT 模式案例

拓扑结构

text 复制代码
Client (外网) → LVS调度器(VIP:192.168.1.100/对外,私有IP:10.0.0.1)→ RS1(10.0.0.11:80)
                                        → RS2(10.0.0.12:80)

LVS 同时拥有外网 IP(VIP)和内网私有 IP。RS 网关需指向 LVS 的内网 IP,响应流量经 LVS 返回客户端。

步骤一:LVS 调度器配置

bash 复制代码
# 开启 IP 转发(必须)
echo 1 > /proc/sys/net/ipv4/ip_forward

# 永久生效:编辑 /etc/sysctl.conf,设置 net.ipv4.ip_forward=1
# 然后执行 sysctl -p

# 添加虚拟服务和 Real Server(NAT 模式使用 -m 参数)
ipvsadm -A -t 192.168.1.100:80 -s rr
ipvsadm -a -t 192.168.1.100:80 -r 10.0.0.11:80 -m
ipvsadm -a -t 192.168.1.100:80 -r 10.0.0.12:80 -m

# 查看配置结果
ipvsadm -Ln

步骤二:Real Server 配置

bash 复制代码
# 两台 RS 需将默认网关设置为 LVS 调度器的内网 IP
route add default gw 10.0.0.1

启动 RS 上的 Web 服务(如 Nginx),监听端口 80。

步骤三:验证

bash 复制代码
curl http://192.168.1.100:80
# 多次执行,观察请求轮询分发到 RS1 和 RS2

5.2 DR 模式案例

拓扑结构

text 复制代码
Client → LVS调度器(VIP:192.168.1.100,DIP:192.168.1.1)→ RS1(192.168.1.11:80)→ 直接返回 Client
                            → RS2(192.168.1.12:80)→ 直接返回 Client

要求 LVS 与 RS 处于同一网段,响应包不经过 LVS。

步骤一:LVS 调度器配置

bash 复制代码
# 配置 VIP(不响应 ARP 的隐藏模式)
ip addr add 192.168.1.100/24 dev eth0 label eth0:0

# 开启 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward

# 添加虚拟服务和 Real Server(DR 模式使用 -g 参数)
ipvsadm -A -t 192.168.1.100:80 -s wrr
ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.11:80 -g
ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.12:80 -g

ipvsadm -Ln

步骤二:Real Server 配置(关键)

每台 RS 需配置 VIP 到 loopback 接口,并抑制 ARP 响应:

bash 复制代码
# 配置 VIP 到 lo:0 接口(避免 ARP 冲突)
ifconfig lo:0 192.168.1.100 netmask 255.255.255.255 broadcast 192.168.1.100 up

# 配置 ARP 抑制,避免 RS 响应 VIP 的 ARP 请求
echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce
echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore
echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce

# 永久配置:写入 /etc/sysctl.conf
net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

步骤三:验证

bash 复制代码
curl http://192.168.1.100:80
ipvsadm -L -n -c    # 查看当前连接状态

6. Keepalived 安装与配置

6.1 安装

bash 复制代码
# CentOS/RHEL
yum install -y keepalived ipvsadm

# Ubuntu/Debian
apt update && apt install -y keepalived ipvsadm

6.2 配置文件完整模板

/etc/keepalived/keepalived.conf 生产环境配置模板:

conf 复制代码
# ==================== 全局定义块 ====================
global_defs {
    router_id LVS_MASTER              # 节点唯一标识,备机改为 LVS_BACKUP
    lvs_id LVS_LOAD_BALANCER          # LVS 标识
    enable_script_security            # 启用脚本安全检查
    # 邮件通知配置(可选)
    notification_email {
        admin@example.com
    }
    notification_email_from keepalived@example.com
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
}

# ==================== VRRP 脚本检测(可选)====================
vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 2                        # 检测间隔(秒)
    weight -20                        # 失败时优先级减20
    fall 2                            # 连续失败2次判定故障
    rise 1                            # 连续成功1次恢复
}

# ==================== VRRP 实例块 ====================
vrrp_instance VI_1 {
    state MASTER                      # 主节点:MASTER;备节点:BACKUP
    interface eth0                    # 绑定的物理网卡
    virtual_router_id 51              # 虚拟路由 ID,主备必须一致(0-255)
    priority 150                      # 优先级:MASTER 需高于 BACKUP
    advert_int 1                      # VRRP 心跳广播间隔(秒)
    
    # 认证配置
    authentication {
        auth_type PASS
        auth_pass 123456              # 密码,主备必须一致
    }
    
    # 虚拟 IP 地址(VIP)
    virtual_ipaddress {
        192.168.10.100/24 dev eth0 label eth0:1
        # 可配置多个 VIP
        # 192.168.10.200/24 dev eth0 label eth0:2
    }
    
    # 调用健康检查脚本
    track_script {
        chk_nginx
    }
    
    # 通知脚本
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}

# ==================== 虚拟服务器块(LVS 配置)====================
virtual_server 192.168.10.100 80 {
    delay_loop 6                      # 健康检查间隔(秒)
    lb_algo wrr                       # 调度算法:rr/wrr/lc/wlc/lblc/sh/dh
    lb_kind DR                        # 工作模式:NAT(-m)/ DR(-g)/ TUN(-i)
    persistence_timeout 60            # 会话保持时间(秒)
    protocol TCP                      # 协议类型
    
    # ==================== Real Server 1 ====================
    real_server 10.0.0.11 80 {
        weight 1                      # 权重
        inhibit_on_failure            # 故障时标记不可用
        TCP_CHECK {                   # TCP 健康检查
            connect_timeout 3         # 连接超时(秒)
            nb_get_retry 3            # 重试次数
            delay_before_retry 2      # 重试前延迟(秒)
            connect_port 80
        }
    }
    
    # ==================== Real Server 2 ====================
    real_server 10.0.0.12 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 2
            connect_port 80
        }
    }
    
    # HTTP 健康检查示例
    # real_server 10.0.0.11 80 {
    #     weight 1
    #     HTTP_GET {
    #         url {
    #             path /health
    #             status_code 200
    #         }
    #         connect_timeout 3
    #         nb_get_retry 3
    #         delay_before_retry 2
    #     }
    # }
}

6.3 启动与管理

bash 复制代码
systemctl start keepalived
systemctl enable keepalived
systemctl status keepalived

# 查看 VIP 状态
ip addr show
# 查看 LVS 规则
ipvsadm -L -n

7. Keepalived + Nginx 高可用案例

场景:两台 Nginx 服务器(业务层),通过 Keepalived 实现高可用切换。

架构

text 复制代码
Client → VIP(192.168.10.100) → Nginx1(192.168.10.11,MASTER)
                            → Nginx2(192.168.10.12,BACKUP)

步骤一:安装 Nginx

两台服务器安装 Nginx:

bash 复制代码
yum install -y nginx
systemctl start nginx

步骤二:创建健康检查脚本

/etc/keepalived/check_nginx.sh 创建:

bash 复制代码
#!/bin/bash
# 检查 Nginx 进程是否存在
if [ -f /var/run/nginx.pid ]; then
    exit 0
else
    exit 1
fi
bash 复制代码
chmod +x /etc/keepalived/check_nginx.sh

步骤三:配置 Keepalived(仅 Nginx 高可用,不加载 LVS)

/etc/keepalived/keepalived.conf

conf 复制代码
global_defs {
    router_id NGINX_MASTER            # 备机改为 NGINX_BACKUP
}

vrrp_script chk_nginx {
    script "/etc/keepalived/check_nginx.sh"
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER                      # 备机改为 BACKUP
    interface eth0
    virtual_router_id 52
    priority 150                      # 备机设置较低的优先级,如 100
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass nginx123
    }
    
    virtual_ipaddress {
        192.168.10.100/24 dev eth0    # VIP
    }
    
    track_script {
        chk_nginx                     # 关联健康检查脚本
    }
    
    # 通知脚本(可选)
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
}

步骤四:启动服务

bash 复制代码
systemctl start keepalived
systemctl enable keepalived

步骤五:验证高可用

bash 复制代码
# 主节点:确认 VIP 已绑定
ip addr show | grep 192.168.10.100

# 停止主节点的 Nginx 或 Keepalived
systemctl stop nginx

# 检查 VIP 是否漂移到备节点
# 在备节点执行:ip addr show | grep 192.168.10.100

8. Keepalived + HAProxy 高可用案例

场景:两台 HAProxy 负载均衡器,通过 Keepalived 实现高可用;HAProxy 将流量分发到后端 Web 服务器集群。

架构

text 复制代码
Client → VIP(192.168.10.100) → HAProxy1(192.168.10.11,MASTER) → Web 集群
                            → HAProxy2(192.168.10.12,BACKUP) → Web 集群

步骤一:安装 HAProxy

两台服务器安装 HAProxy:

bash 复制代码
yum install -y haproxy

步骤二:配置 HAProxy(两台相同)

/etc/haproxy/haproxy.cfg

conf 复制代码
global
    log /dev/log local0
    maxconn 4096
    user haproxy
    group haproxy

defaults
    log global
    mode http
    option httplog
    option dontlognull
    retries 3
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

# 前端:接收来自 VIP 的请求
frontend http-in
    bind *:80                        # 监听所有接口的 80 端口
    default_backend web_servers

# 后端:Web 服务器集群
backend web_servers
    balance roundrobin               # 轮询算法
    option httpchk GET /health       # 健康检查
    server web1 192.168.10.21:80 check inter 2s rise 2 fall 3
    server web2 192.168.10.22:80 check inter 2s rise 2 fall 3

# 统计页面(可选)
listen stats
    bind *:8080
    stats enable
    stats uri /haproxy?stats
    stats auth admin:admin

启动 HAProxy:

bash 复制代码
systemctl start haproxy
systemctl enable haproxy

步骤三:配置 Keepalived(仅 HAProxy 高可用,不加载 LVS)

/etc/keepalived/keepalived.conf

conf 复制代码
global_defs {
    router_id HAPROXY_MASTER          # 备机改为 HAPROXY_BACKUP
}

vrrp_script chk_haproxy {
    script "killall -0 haproxy"       # 检查 haproxy 进程是否运行
    interval 2
    weight -20
}

vrrp_instance VI_1 {
    state MASTER                      # 备机改为 BACKUP
    interface eth0
    virtual_router_id 53
    priority 150                      # 备机优先级 100
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass haproxy123
    }
    
    virtual_ipaddress {
        192.168.10.100/24 dev eth0    # VIP
    }
    
    track_script {
        chk_haproxy
    }
}

步骤四:启动服务

bash 复制代码
systemctl start keepalived
systemctl enable keepalived

步骤五:验证高可用

bash 复制代码
# 主节点:确认 VIP 绑定
ip addr show | grep 192.168.10.100

# 通过 VIP 访问 HAProxy 统计页面
curl http://192.168.10.100:8080/haproxy?stats

# 停止主节点的 HAProxy 进行故障模拟
systemctl stop haproxy

# 验证 VIP 是否漂移到备节点
# 在备节点检查:ip addr show | grep 192.168.10.100

# 重新启动主节点 HAProxy 后,VIP 会漂移回主节点
systemctl start haproxy

步骤六:整合 LVS(可选)

如需 LVS 提供四层负载均衡,在 Keepalived 配置中添加 virtual_server 块(参见第 6 节),将流量分发到两台 HAProxy 的 80 端口,形成 LVS(四层)+ HAProxy(七层)双层负载均衡架构


总结

技术 核心功能 典型组合
MySQL 复制 数据库读写分离、数据冗余、主从切换 一主多从 + 读写分离中间件
LVS 四层负载均衡,高性能流量分发 LVS-DR + Keepalived
Keepalived VRRP 实现 VIP 漂移,健康检查 Keepalived + Nginx / HAProxy / LVS
HAProxy 七层负载均衡,精细化的流量调度 HAProxy + Keepalived

通过以上技术组合,可以构建从数据库层到应用接入层的完整高可用、高性能架构。

9.面试高频模块:MySQL复制 + LVS负载均衡 + Keepalived高可用


一、MySQL 主从复制(高频)

1.1 MySQL 主从复制的原理是什么?有哪些线程参与?

:主从复制基于**二进制日志(binlog)**实现异步数据传输。 三个核心线程:

  • Binlog Dump Thread(主库):读取主库 binlog 事件并发送给从库。
  • I/O Thread(从库):连接主库接收 binlog,写入本地的中继日志(relay log)。
  • SQL Thread(从库):读取 relay log 中的事件并在从库上重放。

流程图简述:主库写 binlog → 从库 I/O 线程拉取 → 写入 relay log → SQL 线程重放。

1.2 主从复制有哪些常见模式?各有什么优缺点?

模式 特点 优点 缺点
异步复制(默认) 主库不关心从库是否接收 性能最高 主库宕机可能丢数据
半同步复制 至少一个从库确认收到 binlog 才提交 数据一致性较好 性能略降,等待从库响应
全同步复制 所有从库都确认后才提交 数据零丢失 性能极差,几乎不用
GTID 复制 基于全局事务 ID,自动定位位点 故障切换方便,无需找位置 对版本有要求

面试追问:你用过半同步吗?如何开启? 答:安装 semisync_master.sosemisync_slave.so,设置 rpl_semi_sync_master_enabled=1

1.3 怎么搭建一主一从?关键参数有哪些?

  1. 主库开启 binlog,设置 server-id=1log-bin=mysql-bin
  2. 创建复制账号 repl 并赋予 REPLICATION SLAVE 权限。
  3. 从库设置 server-id=2relay-log=mysql-relay-binread-only=1
  4. 从库执行 CHANGE MASTER TO 指定主库 IP、账号、密码、日志文件和位置。
  5. START SLAVE 并检查 SHOW SLAVE STATUS\GSlave_IO_RunningSlave_SQL_Running 均为 Yes。

1.4 主从延迟怎么产生?如何优化?

原因

  • 从库硬件差(IO/CPU 瓶颈)
  • 主库大事务(如批量删除、大表 DDL)
  • 从库有慢查询
  • 网络延迟

优化方案

  • 使用 sync_binlog=1 + innodb_flush_log_at_trx_commit=1 保证主库不丢,但会增加延迟(可折中)
  • 从库开启并行复制:slave_parallel_workers=8slave_parallel_type=LOGICAL_CLOCK
  • 避免大事务,拆分 DML
  • 将从库的 binlog_format 设为 ROW,减少 SQL 级解析开销

1.5 主从复制中断了怎么处理?

常见排查流程

  1. 查看 SHOW SLAVE STATUSLast_Error 字段,确定错误原因。
  2. 如果是由于主键冲突或数据不存在,可临时跳过:
    • STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE; (慎用)
  3. 如果是 GTID 复制:
    • STOP SLAVE; SET GTID_NEXT='...'; BEGIN; COMMIT; SET GTID_NEXT='AUTOMATIC'; START SLAVE;
  4. 若无法跳过,建议重做从库:重新备份主库 → 恢复到从库 → 重新 CHANGE MASTER。

二、LVS(Linux Virtual Server)高频

2.1 LVS 是什么?工作在哪一层?

:LVS 是 Linux 内核集成的四层(传输层)负载均衡器,基于 IPVS 模块实现。它在 TCP/UDP 级别分发流量,不解析应用层数据,因此性能极高,适合大并发场景。

2.2 LVS 有哪几种工作模式?简述区别。

模式 转发原理 是否改写 IP 响应是否经过 LVS 要求同网段 性能
NAT 修改目标 IP 地址 是(DNAT) 是(进出都经 LVS) 否(RS 可私有 IP)
DR 修改目标 MAC 地址 否(RS 直接回客户端) 最高
TUN IP 隧道封装 是(新增 IP 头) 否(可跨机房) 较高

场景推荐

  • 内网且对性能要求极高 → DR 模式
  • RS 与 LVS 不在同一物理网络 → TUN 模式
  • 简单测试且 RS 需要隐藏真实 IP → NAT 模式

2.3 LVS 的调度算法有哪些?分别适用什么场景?

静态算法

  • RR(轮询):同性能服务器,短连接。
  • WRR(加权轮询):服务器性能差异大。
  • SH(源地址哈希):会话保持(如需要将同一用户绑定到同一 RS)。
  • DH(目标地址哈希):缓存场景(相同目标 IP 转发到同一缓存服务器)。

动态算法

  • LC(最少连接):长连接服务(如数据库连接、WebSocket)。
  • WLC(加权最少连接):异构服务器下的长连接。
  • SED / NQ:极少用,LC 的优化变种。
  • LBLC:基于局部性的最少连接,适合缓存集群。

面试常问:你们项目中用的是哪种算法?为什么? 回答范例:我们用的是 WRR,因为后端服务器配置不完全相同(有 8C16G 和 4C8G),需要按权重分配;同时由于 HTTP 请求多为短连接,没有采用 LC。

2.4 LVS DR 模式为什么要配置 arp_ignore 和 arp_announce?怎么配?

:因为 DR 模式下 RS 也配置了 VIP(绑定在 lo 上),如果不对 ARP 行为进行限制,RS 会对 VIP 的 ARP 请求做出响应,导致客户端直接访问 RS 而非 LVS。

配置(所有 RS 上执行):

bash

bash 复制代码
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

含义:

  • arp_ignore=1:只回答目标 IP 是接收网卡本地地址的 ARP 请求。
  • arp_announce=2:忽略 IP 包的源地址,选择最合适的本地地址发送 ARP 响应。

2.5 LVS 如何检查后端 RS 的健康状态?

:LVS 本身不具备健康检查功能,通常结合 Keepalived 实现。Keepalived 通过 virtual_server 块中的 TCP_CHECKHTTP_GET 定期探测 RS,若失败则自动从 LVS 规则中移除该 RS。 另外也可使用 ipvsadm 手动添加/删除 RS,或配合 noquorum 服务做外部检测。


三、Keepalived 高频

3.1 Keepalived 是什么?核心原理是什么?

:Keepalived 是一个高可用解决方案,核心基于 VRRP(虚拟路由冗余协议)实现。它通过竞选机制决定 MASTER 和 BACKUP 节点,MASTER 持有虚拟 IP(VIP),BACKUP 监听 MASTER 的心跳,当 MASTER 故障时,BACKUP 自动接管 VIP。同时 Keepalived 集成了对 LVS 的管理和健康检查。

3.2 VRRP 协议中 MASTER 和 BACKUP 是如何选出来的?

  • 每个节点配置 priority(范围 0-255),优先级高者成为 MASTER。
  • MASTER 会定期发送 VRRP 广告(advert_int 间隔),BACKUP 在 master_down_interval 时间内未收到广告则主动抢占。
  • 若设置 nopreempt 可关闭抢占模式。

3.3 Keepalived 如何实现业务进程的联动(比如 Nginx 挂了自动切换)?

:通过 vrrp_script 定义自定义检测脚本,例如:

bash 复制代码
vrrp_script check_nginx {
    script "/usr/bin/killall -0 nginx"
    interval 2
    weight -20
}

然后在 vrrp_instance 中通过 track_script 引用。当脚本返回值非 0(表示 Nginx 故障),Keepalived 会将本机优先级减少 weight 值,若优先级低于 BACKUP 则触发 VIP 漂移。

3.4 你配置过 Keepalived + Nginx 高可用吗?配置文件要点有哪些?

:配置过。核心要点:

  1. 两台服务器安装 Nginx 和 Keepalived。
  2. 主节点 state MASTERpriority 150;备节点 state BACKUPpriority 100
  3. 设置相同的 virtual_router_idauth_pass
  4. 配置 virtual_ipaddress 为 VIP(如 192.168.10.100/24)。
  5. 定义健康检查脚本,检测 Nginx 进程,并关联 track_script
  6. 启动后通过 ip addr show 验证 VIP 是否在主节点上;停止主节点 Nginx 验证漂移。

3.5 Keepalived + HAProxy 与 + LVS 的区别?各自场景?

组合 作用层次 适用场景
Keepalived + LVS 四层负载均衡 + 高可用 需要极高吞吐量、简单分发(如数据库、redis 集群)
Keepalived + HAProxy 七层负载均衡 + 高可用 需要 URL 路由、SSL 卸载、高级健康检查(如 Web、API 网关)
Keepalived + Nginx 七层高可用(Nginx 自身做反向代理) 轻量级、Nginx 已作为 Web 服务器或反向代理

面试官可能会追问:能同时用 LVS + HAProxy 吗? 答:可以,典型架构是 LVS(四层)→ HAProxy(七层)→ 应用服务器。LVS 做入口流量均衡,HAProxy 实现内容路由。


四、综合场景题(重点考察解决思路)

4.1 如果一个 LVS DR 模式下,客户端访问 VIP 不通,可能的原因有哪些?

排查思路

  1. 检查 LVS 主机上 ipvsadm -L -n 是否有对应的 VIP 和 RS 规则。
  2. 检查 LVS 主机上 VIP 是否已正确配置在网卡上(ip addr)。
  3. 检查 RS 上是否配置了 VIP(lo:0)且 arp 参数正确。
  4. 检查 RS 的 Web 服务是否监听正确端口,并可通过 DIP 直接访问。
  5. 网络层面:RS 网关是否指向 LVS(DR 模式不需要),是否在同一广播域。
  6. 查看 LVS 统计信息 ipvsadm -L -n -c 是否有连接记录。

4.2 你设计过 MySQL 高可用方案吗?结合 LVS/Keepalived 如何做?

:常见方案:

  • LVS + Keepalived 做 MySQL 读负载均衡:多台从库配置为 LVS 的 RS,VIP 提供统一读入口。缺点是不支持读写分离,需业务层判断。
  • MHA / MGR + Keepalived:MySQL 主库故障时自动选举新主,Keepalived 负责 VIP 漂移,让业务快速切换到新主。
  • ProxySQL + Keepalived:ProxySQL 自带读写分离,两台 ProxySQL 通过 Keepalived 提供 VIP 高可用。

面试中可回答:我们的业务是读多写少,使用 LVS + Keepalived 将多台从库做负载均衡,主库单独用 Keepalived 做高可用(VIP + MHA)。

4.3 请描述一个完整的 LVS + Keepalived + Nginx + MySQL 高可用 Web 架构。

参考答案

  • 前端:Keepalived 提供 VIP(如 10.0.0.100),两台 LVS(DR 模式)做四层负载均衡。
  • 中间层:LVS 将流量分发到多台 Nginx(七层反向代理)。
  • 应用层:Nginx 将动态请求转发到 PHP-FPM 或 Tomcat 集群。
  • 数据层:MySQL 主从复制 + Keepalived(VIP 指向主库),从库通过 LVS 提供读负载均衡。 整个架构无单点,任意一层故障自动切换。

五、快速记忆口诀

  • MySQL 复制三线程:主库 Binlog Dump,从库 I/O 和 SQL。
  • LVS 三大模式:NAT 改 IP,DR 改 MAC,TUN 套隧道。
  • 调度算法记七种:RR、WRR、LC、WLC、SH、DH、LBLC。
  • Keepalived 三核心:VRRP 抢 VIP,脚本检健康,规则配 LVS。

六、高频配置题

题目:写一个 Keepalived + LVS(DR 模式)的配置片段,要求 VIP 为 192.168.1.200,后端两台 RS(192.168.1.11:80,192.168.1.12:80),算法为 wrr,权重分别为 3 和 1,健康检查方式为 TCP 端口检测。

答案(节选):

conf 复制代码
virtual_server 192.168.1.200 80 {
    delay_loop 6
    lb_algo wrr
    lb_kind DR
    persistence_timeout 60
    protocol TCP
    
    real_server 192.168.1.11 80 {
        weight 3
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 2
            connect_port 80
        }
    }
    real_server 192.168.1.12 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 2
            connect_port 80
        }
    }
}

附加:RS 上需要配置 echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore 等命令并绑定 VIP 到 lo:0。

相关推荐
難釋懷12 小时前
Nginx基于反向代理的负载均衡
nginx·github·负载均衡
源远流长jerry1 天前
LVS 与 Nginx 负载均衡:从原理到生产实战
运维·网络·网络协议·tcp/ip·nginx·负载均衡·lvs
魏杨杨2 天前
被流量逼出来的架构:从一台服务器到云原生的 17 次蜕变 —— 集群、缓存、MQ、微服务、Docker、K8S 的前世今生
微服务·k8s·负载均衡·ddd·分部署
Mr.Java.2 天前
Spring AI MCP Server分布式翻车现场:Streamable协议的甜蜜与危险,以及无状态救赎
java·后端·spring·ai·负载均衡
百度智能云技术站3 天前
多模态模型训练加速,LoongForge 的 DP 负载均衡优化方案详解
负载均衡·dp·多模态大模型
Donk_674 天前
HAProxy实验搭建
运维·负载均衡
yyyyy_abc4 天前
负载均衡与高可用
运维·负载均衡
华万通信king5 天前
腾讯云CLB负载均衡接入实战:高并发Web服务的稳定性配置
前端·负载均衡·腾讯云
文青小兵6 天前
云计算Linux——负载均衡 (十四)
linux·运维·服务器·nginx·云计算·负载均衡