MySQL读写分离部署配置全解析(从原理到落地)

在高并发业务场景中,MySQL数据库单节点往往会面临读写压力失衡的问题------写操作(INSERT/UPDATE/DELETE)需保证数据一致性,无法轻易横向扩展;而读操作(SELECT)占比通常更高,成为性能瓶颈。MySQL读写分离通过"主从复制"实现数据同步,再通过路由组件分发读写请求,让主库专注于写操作,从库承担读操作,从而提升整体并发能力、降低单节点负载。本文将从原理、部署准备、分步配置、测试验证到优化建议,完整讲解MySQL读写分离的落地流程。

一、读写分离核心原理

1. 核心架构组成

MySQL读写分离架构主要包含三个核心组件,协同实现请求分发与数据同步:

  • 主库(Master):唯一处理写请求的节点,同时通过二进制日志(binlog)记录所有数据变更操作,作为数据同步的数据源。

  • 从库(Slave):1个或多个从节点,通过IO线程读取主库的binlog,再通过SQL线程重放日志,实现与主库数据一致;仅处理读请求,分担主库读压力。

  • 路由中间件:接收应用层请求,根据SQL类型分发至对应节点(写请求→主库,读请求→从库),常见组件有MyCat、ProxySQL、Sharding-JDBC等。

2. 数据同步流程(主从复制)

主从复制是读写分离的基础,基于binlog实现异步/半同步数据同步,流程如下:

  1. 主库开启binlog,每执行一次写操作,都会将操作记录到binlog中(按事件格式存储)。

  2. 从库启动后,通过IO线程连接主库,请求主库发送binlog日志(从指定位置开始)。

  3. 主库的dump线程接收请求,将binlog日志增量推送给从库IO线程,从库IO线程将日志写入本地中继日志(relay log)。

  4. 从库的SQL线程读取中继日志,按顺序重放日志中的操作,同步主库数据。

3. 路由分发逻辑

路由中间件通过解析SQL语句的类型,实现请求分发:

  • 写请求(含事务类操作):直接路由至主库,确保数据一致性(避免写操作分散导致的数据冲突)。

  • 读请求:路由至从库(可配置负载均衡策略,如轮询、加权轮询),若从库异常,可自动切换至主库兜底。

二、部署前准备

1. 环境规划

本次部署采用"1主2从+MyCat中间件"架构,服务器配置如下(生产环境建议独立节点,避免资源竞争):

|-------------|---------------|------------------|---------------|----------------------|
| 节点角色 | IP地址 | 操作系统 | MySQL版本 | 核心作用 |
| 主库(Master) | 192.168.1.100 | Ubuntu 20.04 LTS | MySQL 8.0 | 处理写请求,生成binlog |
| 从库1(Slave1) | 192.168.1.101 | Ubuntu 20.04 LTS | MySQL 8.0 | 处理读请求,同步主库数据 |
| 从库2(Slave2) | 192.168.1.102 | Ubuntu 20.04 LTS | MySQL 8.0 | 处理读请求,同步主库数据,实现读负载均衡 |
| MyCat节点 | 192.168.1.103 | Ubuntu 20.04 LTS | MyCat 1.6.7.6 | 请求路由,读写分离分发 |

2. 基础环境配置

所有节点需完成以下基础配置,避免部署过程中出现异常:

  • 关闭防火墙/开放端口:Ubuntu 20.04默认使用ufw防火墙,开放MySQL(3306)、MyCat(8066)端口,或直接关闭ufw(生产环境建议精准开放端口)。

复制代码
    # 开放指定端口并启用
  sudo ufw allow 3306/tcp
  sudo ufw allow 8066/tcp
  sudo ufw enable
  # 若需临时关闭防火墙(测试环境)
  sudo ufw disable
  # Ubuntu无SELinux,无需额外关闭操作
  • 安装依赖:主从节点安装MySQL 8.0(Ubuntu 20.04 apt源自带),MyCat节点安装JDK 1.8。

    复制代码
      # 主从节点安装MySQL 8.0
    sudo apt update
    sudo apt install -y mysql-server mysql-client
    # MyCat节点安装JDK 1.8
    sudo apt install -y openjdk-8-jdk
    # 验证JDK安装
    java -version
  • 时钟同步:Ubuntu 20.04默认搭载systemd-timesyncd服务,启用即可实现时间同步,避免因时间差导致binlog同步失败。

    复制代码
    # 启用时间同步服务
    sudo timedatectl set-ntp on
    # 验证同步状态
    timedatectl status

三、分步部署配置

第一步:配置主库(Master)

主库核心配置是开启binlog,设置唯一节点ID,授权从库同步账号。

  1. 修改MySQL配置文件

    复制代码
     [mysqld]
    # 开启binlog,指定日志存储路径
    log_bin = /var/lib/mysql/mysql-bin.log
    # binlog日志格式(建议ROW,避免语句级同步的一致性问题)
    binlog_format = ROW
    # 主库唯一ID(1-2^32-1,不可与从库重复)
    server-id = 1
    # 仅同步指定数据库(可选,按需配置,不配置则同步所有库)
    binlog_do_db = test_db
    # 忽略同步的数据库(可选)
    binlog_ignore_db = mysql
    binlog_ignore_db = information_schema
    # 确保binlog写入磁盘(提升数据可靠性,生产环境建议开启)
    sync_binlog = 1
    # 禁止从库写入(从库需配置,主库可选)
    read_only = 0
    # 允许超级用户在read_only模式下写入(主库必备)
    super_read_only = 0
  2. 重启MySQL服务:Ubuntu 20.04 MySQL服务名为mysql,命令如下:

    复制代码
    sudo systemctl restart mysql && sudo systemctl enable mysql
  3. 创建从库同步账号并授权:登录MySQL,创建专门用于主从复制的账号,授予复制权限。

    复制代码
     -- 登录MySQL
    mysql -u root -p
    -- 创建同步账号(slave_user为账号,192.168.1.%为从库IP段,可限制具体IP)
    CREATE USER 'slave_user'@'192.168.1.%' IDENTIFIED BY 'Slave@123456';
    -- 授予复制权限
    GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'192.168.1.%';
    -- 刷新权限
    FLUSH PRIVILEGES;
    -- 查看主库binlog状态(记录File和Position值,从库配置需用到)
    SHOW MASTER STATUS;

    执行结果需记录:File(如mysql-bin.000001)、Position(如156),后续从库配置需以此为起点同步。

第二步:配置从库(Slave1/Slave2)

两个从库配置流程一致,核心是指定主库信息,开启同步线程。

  1. 修改MySQL配置文件:编辑/etc/my.cnf,添加以下配置(两个从库server-id需不同):

    复制代码
    [mysqld]
    # 从库唯一ID(Slave1设为2,Slave2设为3,不可重复且不等于主库)
    server-id = 2
    # 开启中继日志(存储主库binlog,用于重放)
    relay_log = /var/lib/mysql/relay-bin.log
    # 中继日志索引文件
    relay_log_index = /var/lib/mysql/relay-bin.index
    # 从库只读(禁止写操作,确保数据与主库一致)
    read_only = 1
    # 超级用户也只读(生产环境建议开启)
    super_read_only = 1
    # 忽略同步错误(可选,避免因小错误导致同步中断)
    slave_skip_errors = 1062
  2. 重启MySQL服务

    复制代码
    sudo systemctl restart mysql && sudo systemctl enable mysql
  3. 配置主从同步参数:登录MySQL,指定主库IP、同步账号、binlog文件及位置,启动同步线程。

    复制代码
    -- 登录MySQL
    mysql -u root -p
    -- 停止现有同步(首次配置可忽略)
    STOP SLAVE;
    -- 配置主库信息
    CHANGE MASTER TO
    MASTER_HOST='192.168.1.100',  -- 主库IP
    MASTER_USER='slave_user',     -- 同步账号
    MASTER_PASSWORD='Slave@123456', -- 同步密码
    MASTER_LOG_FILE='mysql-bin.000001', -- 主库binlog文件名(第一步记录的File)
    MASTER_LOG_POS=156; -- 主库binlog位置(第一步记录的Position)
    -- 启动同步线程
    START SLAVE;
    -- 查看同步状态
    SHOW SLAVE STATUS
  4. 验证同步状态:执行SHOW SLAVE STATUS\G后,需满足两个核心条件,说明同步正常:Slave_IO_Running: Yes(IO线程正常,能读取主库binlog)

  5. Slave_SQL_Running: Yes(SQL线程正常,能重放中继日志)

第三步:配置MyCat中间件(路由分发)

MyCat作为路由中间件,通过配置文件实现读写分离规则,应用层只需连接MyCat,无需感知主从节点。

  1. 安装MyCat:Ubuntu 20.04解压安装步骤一致,补充依赖检查命令:

    复制代码
    # 确认JDK已安装
    java -version
    # 下载MyCat压缩包
    wget http://dl.mycat.org.cn/1.6.7.6/20220524173829/Mycat-server-1.6.7.6-release-20220524173829-linux.tar.gz
    # 解压至/usr/local目录
    sudo tar -zxvf Mycat-server-1.6.7.6-release-20220524173829-linux.tar.gz -C /usr/local/
    # 配置环境变量(可选)
    echo "export MYCAT_HOME=/usr/local/mycat" | sudo tee -a /etc/profile
    source /etc/profile
    # 授权MyCat目录权限
    sudo chmod 755 -R /usr/local/mycat
  2. 核心配置文件修改:MyCat的读写分离规则主要通过3个文件配置,均位于/usr/local/mycat/conf目录。 (1)schema.xml(定义逻辑库、数据源、读写规则

    复制代码
    <?xml version="1.0"?>
    <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
    <mycat:schema xmlns:mycat="http://io.mycat/"&gt;
      <!-- 逻辑库名称(应用层连接时使用),与物理库test_db对应 -->
      <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"/&gt;
      <!-- 数据节点,指定物理数据库 -->
      <dataNode name="dn1" dataHost="localhost1" database="test_db"/>
      <!-- 数据源配置,指定主从节点信息 -->
      <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
                writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <!-- 主库配置(写节点) -->
        <writeHost host="hostM1" url="192.168.1.100:3306" user="root" password="Root@123456">
    <!-- 从库配置(读节点),两个从库依次配置 -->
          <readHost host="hostS1" url="192.168.1.101:3306" user="root" password="Root@123456"/>
          <readHost host="hostS2" url="192.168.1.102:3306" user="root" password="Root@123456"/>
        </writeHost>
      </dataHost>
    </mycat:schema>

    关键参数说明:(2)server.xml(配置应用层访问账号)

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mycat:server SYSTEM "server.dtd">
    <mycat:server xmlns:mycat="http://io.mycat/">
      <user name="mycat_user" defaultAccount="true">
        <property name="password">Mycat@123456</property>
        <property name="schemas">TESTDB</property><!-- 关联逻辑库TESTDB -->
      </user>
    </mycat:server>

    应用层将通过账号mycat_user、密码Mycat@123456连接MyCat。(3)rule.xml(分片规则,读写分离无需修改,默认即可)若无需分库分表,保持默认配置,仅用于定义路由规则占位。

    1. balance="1":读请求分发至所有从库,实现读负载均衡。

    2. writeType="0":写请求仅分发至第一个writeHost(主库)。

    3. switchType="1":主库故障时,自动切换至从库(需配合心跳检测)。

  3. 启动MyCat:Ubuntu 20.04下启动命令一致,补充日志权限说明:

    复制代码
    # 启动MyCat
    sudo /usr/local/mycat/bin/mycat start
    # 查看启动状态
    sudo /usr/local/mycat/bin/mycat status
    # 日志位置(排查启动异常用,若权限不足可加sudo)
    sudo tail -f /usr/local/mycat/logs/wrapper.log

    MyCat默认端口为8066(数据端口)、9066(管理端口)。

四、读写分离测试验证

测试核心是验证"写请求走主库、读请求走从库",且主从数据同步正常。

1. 连接MyCat测试

复制代码
# 应用层连接MyCat(使用MyCat账号密码,端口8066)
mysql -u mycat_user -pMycat@123456 -h 192.168.1.103 -P 8066

2. 写操作测试(验证走主库)

复制代码
-- 连接MyCat后,执行写操作(插入数据)
USE TESTDB;
INSERT INTO user (id, name, age) VALUES (1, 'test_user', 25);
-- 分别登录主库、从库,查看数据是否同步
-- 主库查询
mysql -u root -p -h 192.168.1.100 -e "SELECT * FROM test_db.user;"
-- 从库1查询
mysql -u root -p -h 192.168.1.101 -e "SELECT * FROM test_db.user;"

结果:主库、从库均能查询到新增数据,说明写操作成功路由至主库,且主从同步正常。Ubuntu 20.04可通过以下命令快速验证主从数据(无需交互输入密码):

复制代码
# 主库查询(需提前配置MySQL免密或输入密码)
sudo mysql -u root -p -h 192.168.1.100 -e "SELECT * FROM test_db.user;"
# 从库1查询
sudo mysql -u root -p -h 192.168.1.101 -e "SELECT * FROM test_db.user;"

3. 读操作测试(验证走从库)

通过开启MySQL慢查询日志,验证读请求是否分发至从库:

  1. 在两个从库开启慢查询日志(记录所有读请求):

    复制代码
    SET GLOBAL slow_query_log = 1;
    SET GLOBAL slow_query_log_file = '/var/lib/mysql/slow.log';
    SET GLOBAL long_query_time = 0; -- 记录所有查询(包括快速查询)
  2. 连接MyCat执行读操作:

    复制代码
    SELECT * FROM test_db.user;
  3. 查看从库慢查询日志: tail -f /var/lib/mysql/slow.log结果:从库1或从库2的日志中会出现该查询记录,主库慢查询日志无记录,说明读请求成功路由至从库。

4. 负载均衡测试(多从库场景)

多次执行读操作,观察两个从库的慢查询日志,会发现请求按轮询方式分发至两个从库,实现读负载均衡。

五、常见问题排查

1. 主从复制失败(IO/SQL线程为No)

  • IO线程失败:检查主从网络是否通(ping、telnet 3306端口)、同步账号密码是否正确、主库binlog文件/位置是否错误。

  • SQL线程失败:通常是主从数据不一致(如从库已有相同主键数据),可通过slave_skip_errors跳过错误,或重新初始化从库数据(备份主库数据导入从库)。

2. 读写分离路由异常(读请求走主库)

  • 检查MyCat的schema.xml中balance参数是否为1(非0),readHost配置是否正确。

  • 确认SQL语句是否为纯读操作(若包含事务,MyCat会路由至主库)。

3. 数据不一致(主从数据不同步)

可能是主库binlog格式设置不当(建议ROW格式),或从库同步延迟。可通过调整sync_binlog、innodb_flush_log_at_trx_commit参数提升同步可靠性,或开启MySQL半同步复制(需额外配置)。

六、生产环境优化建议

1. 性能优化

  • 主库参数优化:调整binlog相关参数(sync_binlog=1、innodb_flush_log_at_trx_commit=1),平衡性能与可靠性。

  • 从库参数优化:关闭binlog(从库无需生成binlog)、调整join_buffer_size、sort_buffer_size提升读性能。

  • MyCat优化:调整maxCon(最大连接数)、优化心跳检测频率,避免频繁检测占用资源。

2. 高可用优化

  • 主库高可用:通过MHA、Keepalived实现主库故障自动切换,避免主库单点故障。

  • 从库高可用:增加从库节点,避免单个从库故障导致读请求中断。

  • MyCat高可用:部署多个MyCat节点,通过Keepalived实现VIP漂移,避免中间件单点故障。

3. 监控告警

通过Prometheus+Grafana、Zabbix等工具,监控主从同步状态(IO/SQL线程、同步延迟)、MyCat连接数、主从库负载,设置告警阈值(如同步延迟超过30秒告警),及时发现异常。

七、总结

MySQL读写分离通过"主从复制+路由中间件"的组合,有效解决了高并发场景下的读写压力失衡问题,是数据库水平扩展的基础方案。本文基于MySQL 8.0+MyCat实现了读写分离部署,核心在于主从复制的稳定配置和路由规则的精准定义。生产环境中,需结合业务场景优化参数、保障高可用、完善监控,才能充分发挥读写分离的性能优势。

后续可进一步探索分库分表(与读写分离结合)、MySQL 8.0新特性(如GTID复制)对读写分离的优化,适配更复杂的业务场景。

相关推荐
shengli7222 小时前
Python Lambda(匿名函数):简洁之道
jvm·数据库·python
rustfs2 小时前
RustFS 配置 Cloudflare Tunnel 实现安全访问的详细教程!
分布式·安全·docker·rust·开源
weixin_445402302 小时前
如何为开源Python项目做贡献?
jvm·数据库·python
2301_821369612 小时前
数据分析与科学计算
jvm·数据库·python
SJLoveIT2 小时前
CAP理论,顺便讲下BASE
分布式
TracyCoder1232 小时前
MySQL 实战宝典(二):MySQL vs Elasticsearch 文本检索性能全方位对比
数据库·mysql·elasticsearch
m0_737539372 小时前
Mariadb 服务器
服务器·数据库·mariadb
indexsunny2 小时前
互联网大厂Java面试实战:Spring Boot微服务在电商场景中的应用
java·数据库·spring boot·redis·微服务·kafka·电商
广药门徒2 小时前
WS2812_CONTROL使用手册
android·java·数据库