MySQL 主从复制与 Amoeba 读写分离实验记录
一、实验概述
1.1 实验背景
MySQL主从复制与读写分离通过数据冗余、读写负载分离、弹性扩展等机制,显著提升了系统的性能、可用性及可维护性,尤其适合高并发、数据驱动型业务。实际应用中需结合业务特点选择合适的复制模式(异步/半同步)和工具链,并关注延迟监控与故障恢复设计。
1.2 实验环境
-
VMware 虚拟机环境简介
-
节点 数量 IP 系统 角色 MASTER主库 1 192.168.100.24 centos7 唯一写入入口,强一致性源头 SLAVE从库 2 192.168.100.31、192.168.100.33 ubuntu-22 读扩展、灾备恢复、数据分析 Amoeba服务器 1 192.168.100.35 ubuntu-22 读写分离、负载均衡、故障转移 -
软件版本:mysql-8.0.41、amoeba-mysql-binary-2.2.0、jdk-6u14-linux-x64等(链接已分享至文末,按需自取)
二、前期准备
2.1 虚拟机网络配置
- 配置 VMware 网络模式,确保三台主机在同一网段且能相互通信
- 分别在三台主机上配置静态 IP 地址
2.2 系统基础设置
- 关闭防火墙和 SELinux(主机 A)或 UFW(主机 B 和 C)
- 更新系统软件包
2.3 MySQL 安装
-
在主机 A、B、C 上分别安装 MySQL 数据库
-
配置 MySQL 开机自启
三、MySQL 主从复制配置
3.1 主库配置
3.1.1 修改 MySQL 配置文件
-
编辑
my.cnf
文件,开启二进制日志、设置唯一的server-id
等
server-id #必须唯一,主与从从与从之间都不能相同
innodb_buffer_pool_size #不能超过服务器内存,否则报错
relay-log=relay-bin #从服务器才需要的中继服务器
log-bin=mysql-bin #添加,主服务器开启二进制日志
slave_parallel_workers #从服务器并行线程
slave_parallel_type=LOGICAL_CLOCK #从服务器并发复制
default_authentication_plugin=mysql_native_password #mysql8.0需要修改身份验证插件,从8.0开始默认使用caching_sha2_password
innodb_flush_log_at_trx_commit=1 #"双1设置",数据写入最安全
3.1.2 创建用于主从复制的用户
mysql>CREATE USER 'myslave'@'192.168.100.%' IDENTIFIED WITH mysql_native_password BY '123456'; #创建专门用户
mysql>GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.100.%'; #给从服务器授权
FLUSH PRIVILEGES; #刷新立马生效
show master status;
3.1.3 重启 MySQL 服务
3.2 从库(主机 B 和 C)配置
3.2.1 修改 MySQL 配置文件
-
编辑
my.cnf
文件,设置唯一的server-id
server-id = 2/3 #修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-bin #开启中继日志,从主服务器上同步日志文件记录到本地
#选配项
innodb_buffer_pool_size=2048M #用于缓存数据和索引的内存大小,让更多数据读写在内存中完成,减少磁盘操作,可设置为服务器总可用内存的 70-80%
sync_binlog=0 #MySQL不做任何强制性的磁盘刷新指令,而是依赖操作系统来刷新数据到磁盘
innodb_flush_log_at_trx_commit=2 #每次事务log buffer会写入log file,但一秒一次刷新到磁盘
log-slave-updates=0 #slave 从 master 复制的数据会写入二进制日志文件里,从库做为其他从库的主库时设置为 1
relay_log_recovery=1 #当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log, 并且重新从 master 上获取日志,这样就保证了 relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。
skip_slave_start=1 #阻止从库崩溃后自动启动复制,崩溃后再自动复制可能会导致数据不一致的
3.2.2 连接主库
- 在从库上执行
CHANGE MASTER TO
语句,指定主库的信息
CHANGE master to master_host='主库IP',master_port=默认3306,master_user='myslave',master_password='123456',master_log_file='mysql-bin.000009',master_log_pos=1917; #master_log_file和master_log_pos对应的是主库show master status下的File列和Position列对应的参数,必须一致
3.2.3 启动从库复制进程
-
执行
START SLAVE
语句启动复制进程start slave; #启动同步,如有报错执行 reset slave; show slave status\G #查看 Slave 状态 \\确保 IO 和 SQL 线程都是 Yes,代表同步正常 Slave_IO_Running: Yes #负责与主机的io通信 Slave_SQL_Running: Yes #负责自己的slave mysql进程
-
检查从库状态,确保
Slave_IO_Running
和Slave_SQL_Running
都为Yes
3.3 主从复制测试
- 在主库上创建数据库、表并插入数据
- 在从库上检查数据是否同步
四、Amoeba 安装与配置
4.1Java环境配置
因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用
- 下载 JDK 安装包并解压到指定目录
cd /usr/local
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin
\\一直空格然后键入yes即可
- 添加环境变量
vim /etc/profile.d/amoeba.sh
export AMOEBA_HOME=/usr/local/amoeba
export JAVA_HOME=/usr/local/jdk1.6.0_14
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin
export PATH=$PATH:$AMOEBA_HOME/bin
source /etc/profile.d/amoeba.sh
echo $PATH
4.2 Amoeba 安装
-
下载 Amoeba 安装包并解压到指定目录
tar xf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ cd /usr/local/amoeba/bin ./amoeba
4.3 配置 Amoeba 读写分离,两个 Slave 读负载均衡
- 在主库创建Amoeba使用的数据库和账号
CREATE DATABASE IF NOT EXISTS test;
CREATE USER 'amoeba'@'192.168.100.%' IDENTIFIED BY '123456';
GRANT ALL PRIVILEGES ON *.* TO 'amoeba'@'192.168.100.%';
4.4配置amoeba服务
4.4.1修改amoeba.xml核心参数
cd /usr/local/amoeba/conf/
#养成备份好习惯
cp amoeba.xml amoeba.xml.bak
cp dbServers.xml dbServers.xml.bak
vim amoeba.xml
--30行--设置amoeba登录用户
<property name="user">root</property>
--32行-- 设置amoeba登录用户密码
<property name="password">gs941206</property>
--115行--
<property name="defaultPool">master</property>
--117-去掉注释-
<property name="writePool">master</property>
<property name="readPool">slaves</property>
4.4.2修改dbServers.xml定义参数
vim dbServers.xml
--23行--修改
<property name="schema">test</property>
--26--修改
<property name="user">amoeba</property>
--28-30--去掉注释
<property name="password">123456</property>
--45--修改,设置主服务器的名Master
<dbServer name="master" parent="abstractServer">
--48--修改,设置主服务器的地址
<property name="ipAddress">192.168.80.10</property>
--52--修改,设置从服务器的名slave1
<dbServer name="slave1" parent="abstractServer">
--55--修改,设置从服务器1的地址
<property name="ipAddress">192.168.80.11</property>
--58--复制上面6行粘贴,设置从服务器2的名slave2和地址
<dbServer name="slave2" parent="abstractServer">
<property name="ipAddress">192.168.80.12</property>
--65行--修改
<dbServer name="slaves" virtual="true">
--71行--修改
<property name="poolNames">slave1,slave2</property>
4.3.3 启动 Amoeba 服务
- 回到/usr/local/amoeba/bin目录
./amoeba start &
五、读写分离测试
5.1 客户端连接 Amoeba
- 使用 Navicat客户端连接到 Amoeba 服务
5.2 读写操作测试
- 执行写操作(如插入、更新、删除),检查数据是否写入主库
- 执行读操作,检查数据是否从从库读取
六、实验总结
7.1 主从复制原理
- 主库master如果发生数据更新,会将写入操作记录到自己的二进制日志中
- 从库slave探测到主库的二进制日志发生了更新,就会开启IO线程向主库请求二进制日志事件
- 主库会为每个从库的IO线程请求开启DUMP线程,并发送二进制日志事件给从库
- 从库接收到二进制日志事件后会保存到自己的中继日志中
- 从库开启SQL线程读取中继日志中的事件,并在本地进行重放(将事件解析成SQL语句逐一执行),从而实现从库和从库的数据一致
(关键词:两个日志 二进制日志(bin log)、中继日志(relay log),三个线程 IO线程 SQL线程 DUMP线程)
7.2 读写分离方式
- 基于程序代码内部实现,根据select、insert进行路由分类,优点是性能较好,因为是程序代码内实现不需要额外的设备开支,缺点是只能开发人员维护,运维人员无从下手,且大型又复杂的应用改动难度较大
- 基于中间代理层实现,除了本文提到的Amoeba或类似工具Mycat,还可以用MySQL-Proxy为MySQL开源项目,通过Lua脚本实现读写分离
7.3软件下载链接
jdk-6u14-linux-x64.bin: https://pan.baidu.com/s/17R_s-eY6p_YZ01H4pJE6yg?pwd=kbsf 提取码: kbsf
mysql-8.0.41: https://pan.baidu.com/s/1SQ8WIHtL37j6ZMNEgxTrLw?pwd=f3i5 提取码: f3i5
amoeba-mysql-binary-2.2.0: https://pan.baidu.com/s/1QMCuVOs7yvNVYDUupy-S3Q?pwd=6883 提取码: 6883