MySQL 主从复制与读写分离详解


一、前言

在企业应用中,成熟的业务通常数据量都比较大。单台 MySQL 在安全性、高可用性和高并发方面都无法满足实际的需求。因此,通常需要配置多台主从数据库服务器,实现读写分离,以提升数据库的整体性能与可用性。


二、主从复制原理

2.1 MySQL 的复制类型

  • 基于语句的复制(STATEMENT):MySQL 默认类型。
  • 基于行的复制(ROW)
  • 混合类型的复制(MIXED)

2.2 MySQL 主从复制的工作过程

主从复制依赖于“两日志、三线程”机制:

  • 两日志

    • Binary log(二进制日志)
    • Relay log(中继日志)
  • 三线程

    • Master 的 Dump Thread
    • Slave 的 I/O Thread
    • Slave 的 SQL Thread

工作流程

  1. Master 将数据更新写入 Binary log。
  2. Slave 的 I/O Thread 读取 Master 的 Binary log 并写入 Relay log。
  3. Slave 的 SQL Thread 读取 Relay log 并重放事件,更新 Slave 数据。

注意:复制在 Slave 上是串行化的,Master 的并行操作在 Slave 上无法并行执行。

2.2.1 MySQL 主从复制延迟

常见延迟原因:

  1. Master 高并发,事务量大。
  2. 网络延迟。
  3. 硬件性能差异(CPU、内存、硬盘 I/O)。
  4. 异步复制机制。

优化建议

  • 调整 MySQL 参数(如 innodb_buffer_pool_size)。
  • 使用高性能硬件,避免云主机,推荐物理机+SSD。
  • 网络优化,避免跨机房同步。
  • 使用半同步或并行复制。

2.3 MySQL 同步方式

  1. 异步复制(Async Replication):默认方式,性能最佳,但可能丢失数据。
  2. 同步复制(Sync Replication):安全性最高,但性能较差。
  3. 半同步复制(Semi-Sync Replication):折中方案,确保至少一个 Slave 接收日志。
  4. 增强半同步复制(Lossless Semi-Sync):MySQL 5.7+ 默认,数据一致性更强。

2.4 MySQL 应用场景

MySQL 主要处理读和写操作,通常读请求更多。通过主从复制可实现读写分离,从而提升并发处理能力。

架构演变方向

  1. 单点 MySQL → 主从复制
  2. 主从复制 → 读写分离
  3. 读写分离 → 高可用架构(如 MHA、MGR、MMM)

三、主从复制实验

环境准备

  • Master:192.168.10.16
  • Slave1:192.168.10.14
  • Slave2:192.168.10.15
  • Amoeba:192.168.10.80(读写分离代理)
  • Client:192.168.10.13(测试端)

3.1 时间同步配置

Master 配置:
yum install ntp -y
vim /etc/ntp.conf
# 添加:
server 127.127.1.0
fudge 127.127.1.0 stratum 10

systemctl start ntpd
systemctl stop firewalld
setenforce 0
Slave 配置:
yum install ntp ntpdate -y
ntpdate 192.168.10.16
# 设置定时同步:
crontab -e
*/10 * * * * /usr/sbin/ntpdate 192.168.10.16

3.2 MySQL 安装(略)

三台服务器均需安装 MySQL 5.7。

3.3 主从同步配置

Master 配置:
vim /etc/my.cnf
[mysqld]
log_bin=master-bin
log_slave_updates=true
server_id=1

systemctl restart mysqld

mysql -uroot -p
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.10.%' IDENTIFIED BY '123456';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;
Slave 配置:
vim /etc/my.cnf
[mysqld]
log_bin=master-bin
server_id=22  # Slave2 设为 23
relay_log=relay-log-bin
relay_log_index=slave-relay-bin.index

systemctl restart mysqld

mysql -uroot -p
CHANGE MASTER TO
MASTER_HOST='192.168.10.16',
MASTER_USER='myslave',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='master-bin.000001',
MASTER_LOG_POS=412;

START SLAVE;
SHOW SLAVE STATUS\G;

3.4 测试同步

在 Master 上创建数据库:

CREATE DATABASE work;

在 Slave 上检查是否同步成功。


四、MySQL 读写分离

4.1 什么是读写分离?

  • 写操作(INSERT/UPDATE/DELETE)由 Master 处理。
  • 读操作(SELECT)由 Slave 处理。

4.2 为什么需要读写分离?

  • 写操作耗时,影响读性能。
  • 读写分离可提升查询效率,分担数据库压力。

4.3 何时使用?

  • 读多写少的场景。
  • 高并发查询需求。

4.4 实现方式

  1. 代码层实现:在程序中区分读写路由。
  2. 中间件代理:如 MySQL-Proxy、Atlas、Amoeba。

4.5 企业应用场景

  • Amoeba 易用性强,广泛应用于生产环境。
  • 不支持事务和存储过程,但适合大多数读写分离场景。

五、读写分离实验(Amoeba)

5.1 环境说明

  • Amoeba 服务器:192.168.10.80
  • 需提前搭建一主两从环境。

5.2 安装与配置

安装 JDK:
cd /opt
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin
mv jdk1.6.0_14 /usr/local/jdk1.6

vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
source /etc/profile
安装 Amoeba:
mkdir /usr/local/amoeba
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
配置 Amoeba:
<!-- amoeba.xml -->
<property name="user">amoeba</property>
<property name="password">123456</property>
<property name="defaultPool">master</property>
<property name="writePool">master</property>
<property name="readPool">slaves</property>

<!-- dbServers.xml -->
<property name="user">test</property>
<property name="password">123456</property>
<dbServer name="master" parent="abstractServer">
  <property name="ipAddress">192.168.10.16</property>
</dbServer>
<!-- 类似配置 slave1、slave2 -->
启动 Amoeba:
/usr/local/amoeba/bin/amoeba start&
netstat -anpt | grep java

5.3 测试读写分离

在客户端连接 Amoeba:

mysql -u amoeba -p123456 -h 192.168.10.80 -P8066

进行读写测试,观察数据路由情况。


六、总结

MySQL 主从复制与读写分离是提升数据库性能与可用性的核心方案。通过主从同步实现数据备份与负载均衡,通过读写分离提升查询性能,适用于高并发、大数据量的企业场景。

二进制日志(Binary Log)是 MySQL 复制和恢复的基础,记录所有数据变更操作,不记录查询操作。


附录:常见故障处理方法见原文档第12–13页。

如有同步错误,可尝试:

STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
START SLAVE;

或重新指定 Binlog 位置:

CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=0;

参考资料:MySQL 官方文档、Amoeba 官方文档、CSDN 技术博客等。


版权声明:本文内容仅供参考学习,请勿用于商业用途。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐