Mysql 主从复制、读写分离
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
工作流程:
- Master 将数据更新写入 Binary log。
- Slave 的 I/O Thread 读取 Master 的 Binary log 并写入 Relay log。
- Slave 的 SQL Thread 读取 Relay log 并重放事件,更新 Slave 数据。
注意:复制在 Slave 上是串行化的,Master 的并行操作在 Slave 上无法并行执行。
2.2.1 MySQL 主从复制延迟
常见延迟原因:
- Master 高并发,事务量大。
- 网络延迟。
- 硬件性能差异(CPU、内存、硬盘 I/O)。
- 异步复制机制。
优化建议:
- 调整 MySQL 参数(如
innodb_buffer_pool_size
)。 - 使用高性能硬件,避免云主机,推荐物理机+SSD。
- 网络优化,避免跨机房同步。
- 使用半同步或并行复制。
2.3 MySQL 同步方式
- 异步复制(Async Replication):默认方式,性能最佳,但可能丢失数据。
- 同步复制(Sync Replication):安全性最高,但性能较差。
- 半同步复制(Semi-Sync Replication):折中方案,确保至少一个 Slave 接收日志。
- 增强半同步复制(Lossless Semi-Sync):MySQL 5.7+ 默认,数据一致性更强。
2.4 MySQL 应用场景
MySQL 主要处理读和写操作,通常读请求更多。通过主从复制可实现读写分离,从而提升并发处理能力。
架构演变方向:
- 单点 MySQL → 主从复制
- 主从复制 → 读写分离
- 读写分离 → 高可用架构(如 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 10systemctl 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=1systemctl restart mysqldmysql -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.indexsystemctl restart mysqldmysql -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 实现方式
- 代码层实现:在程序中区分读写路由。
- 中间件代理:如 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.6vim /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 技术博客等。
版权声明:本文内容仅供参考学习,请勿用于商业用途。