mysql主从复制读写分离

主从复制和读写分离

主从复制 核心原理

必须记住 3 个核心组件

  1. binlog(二进制日志) ------ 主库
  2. IO 线程 ------ 从库
  3. SQL 线程 ------ 从库
    完整流程
  4. 主库执行增删改(insert/update/drop)
  5. MySQL 把这些操作记录到 binlog 日志文件
  6. 从库的 IO 线程连接主库,请求 binlog
  7. 主库的 dump 线程把 binlog 发给从库
  8. 从库 IO 线程将内容写到本地 relay log(中继日志)
  9. 从库 SQL 线程读取中继日志,重放 SQL 语句
  10. 两个 Yes 代表正常:IO_Running、SQL_Running
  11. 从库数据和主库完全一致

计划拓扑图

配置时间同步

通过时间戳实现业务的一致性

bash 复制代码
# 所有节点
ntpdate ntp.aliyun.com
date -R
systemctl disable firewalld --now
setenforce 0

mysql主从服务器配置

mysql主服务器配置

bash 复制代码
[root@mysql-master ~]# vim /etc/my.cnf
server-id = 11
log-bin = master-bin      #主服务器日志文件
log-slave-updates = true   #从服务器更新二进制日志

[root@mysql-master ~]# systemctl restart mysqld
##登陆mysql
[root@mysql-master ~]# mysql -u root -p

mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.108.%' IDENTIFIED BY
'123456';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

mysql> show master status;
+-------------------+----------+--------------+------------------+---------------
----+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+---------------
----+
| master-bin.000001 | 604 | | |
|
+-------------------+----------+--------------+------------------+---------------
----+
1 row in set (0.00 sec)

#检查有没有master-bin.000001
[root@mysql-master ~]# ls /usr/local/mysql/data
auto.cnf ibdata1 ib_logfile1 master-bin.000001 mysql
sys ib_buffer_pool ib_logfile0 ibtmp1 master-bin.index performance_schema

mysql从服务器配置

mysql-slave01,mysql-slave02都要做如下操作

bash 复制代码
#主从是克隆的要做这个操作,否则UUID一致
[root@mysql-slave01 ~]# systemctl stop mysqld
[root@mysql-slave01 ~]# rm -f /usr/local/mysql/data/auto.cnf
[root@mysql-slave01 ~]# systemctl start mysqld
[root@mysql-slave01 ~]# vim /etc/my.cnf
server-id = 22 #另外一台为23
relay-log = relay-log-bin #从主服务器上同步日志文件记录到本地
relay-log-index = slave-relay-bin.index #定义relay-log的位置和名称
[root@mysql-slave01 ~]# systemctl restart mysqld
[root@mysql-slave01 ~]# mysql -u root -p
Enter password:

mysql> change master to master_host='192.168.108.101',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=604;
#master_log_file,master_log_pos与前面查询的相同
Query OK, 0 rows affected, 2 warnings (0.03 sec)

mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.108.101
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 604
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes    #Yes
Slave_SQL_Running: Yes     #Yes   确保有2个yes
Replicate_Do_DB:
Replicate_Ignore_DB:
...

slave02节点也是一样操作
##注意配置文件修改,其他一样
[root@mysql-slave02 ~]# vim /etc/my.cnf
server-id = 23
relay-log = relay-log-bin
relay-log-index = slave-relay-bin.index

验证主从同步

bash 复制代码
# 主服务器上:
[root@mysql-master ~]# mysql -uroot -phuawei

mysql> create database school;
Query OK, 1 row affected (0.01 sec)

mysql> use school;

mysql> CREATE TABLE student (
id int UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
age tinyint UNSIGNED,
#height DECIMAL(5,2),
gender ENUM('M','F') default 'M'
)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;

mysql> insert student (name,age)values('路飞',20);

# 去从服务器上 show databases;
[root@mysql-slave01 ~]# mysql -uroot -phuawei
mysql> select * from school.student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
+----+--------+------+--------+
1 row in set (0.00 sec)

amoeba服务器

读写分离 核心原理

基于 主从复制:

  1. 主库写入数据 → 自动同步到从库
  2. 应用程序收到 SQL:
    insert/update/delete → 走主库
    select → 走从库

Amoeba 是一款基于 Java 开发的 MySQL 数据库代理中间件,核心定位是SQL 路由

1.应用 ↔ Amoeba ↔ MySQL 主从集群,Amoeba 是中间 "SQL 路由器"

2.核心能力:自动识别 SQL 类型,写(INSERT/UPDATE/DELETE)走主库,读(SELECT)走从库,并对从库做负载均衡。

3.依赖前提:必须先搭好 MySQL 主从复制,Amoeba 只负责路由,不负责数据同步

工作流程(读写分离)

  1. 应用连接 Amoeba 代理(默认端口 8066),而非直接连 MySQL。
  2. Amoeba 解析 SQL:
    写操作 → 转发到配置的 主库池(writePool)。
    读操作 → 转发到配置的 从库池(readPool),并按轮询 / 权重做负载均衡。
  3. 主从复制保证从库数据与主库一致,应用无感知。

核心组件(配置文件)

amoeba.xml 代理核心配置:端口、认证、读写池、路由规则、线程池

dbServers.xml 定义后端 MySQL 节点(主 / 从)、连接信息、连接池

bash 复制代码
#普通linux克隆得出amoeba
[root@amoeba ~]# hostnamectl set-hostname amoeba
[root@amoeba ~]# systemctl stop firewalld.service
[root@amoeba ~]# setenforce 0

[root@amoeba ~]# chmod +x jdk-6u14-linux-x64.bin
[root@amoeba ~]# ./jdk-6u14-linux-x64.bin
#到yes的时候,输入yes按enter

[root@amoeba ~]# mv jdk1.6.0_14/ /usr/local/jdk1.6

[root@amoeba ~]# vim /etc/profile
最下面加
export JAVA_HOME=/usr/local/jdk1.6    #java家目录
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib  #类环境和jre
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba    #指定amoeba路径
export PATH=$PATH:$AMOEBA_HOME/bin

[root@amoeba ~]# source /etc/profile
[root@amoeba ~]# mkdir /usr/local/amoeba
[root@amoeba ~]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
[root@amoeba ~]# chmod -R 755 /usr/local/amoeba/

#执行结果显示amoeba start|stop说明安装成功
[root@amoeba ~]# /usr/local/amoeba/bin/amoeba
amoeba start|stop

在三台mysql上添加权限开放给amoeba访问

bash 复制代码
#amooba访问数据库的账号
#mysql-master
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';

#mysql-slave01
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';

#mysql-slave02
mysql> grant all on *.* to test@'192.168.108.%' identified by '123.com';

回到amoeba服务器

bash 复制代码
[root@amoeba ~]# cd /usr/local/amoeba/
[root@amoeba amoeba]# vim conf/amoeba.xml
---30行--
<property name="user">amoeba</property  #客户端访问amoeba账号

----32行---------
<property name="password">123456</property>  #客户端访问ameoba密码

---117和120-去掉注释115行 <property name="defaultPool">master</property>
116
117
118行<property name="writePool">master</property>
119行<property name="readPool">slaves</property>
120

####################################################################################
[root@amoeba amoeba]# vim conf/dbServers.xml #数据库配置
---23--注意!!!(mysql5.7,默认没有test数据库所以需要修改为mysql数据库)-(mysql5.5直接忽
略)--
<!-- mysql schema -->
<property name="schema">mysql</property>
--25行到30行,第30行-->移动到28行后面
25 <!-- mysql user -->
26 <property name="user">test</property>
27
28 <!-- mysql password -->
29 <property name="password">123.com</property>
30

-----45到50行主服务器地址---
45行<dbServer name="master" parent="abstractServer">
48行<property name="ipAddress">192.168.108.101</property>

--52到57行从服务器主机名52行
<dbServer name="slave1" parent="abstractServer">
<property name="ipAddress">192.168.108.102</property>
---52到57行复制一份在58行后面
<dbServer name="slave2" parent="abstractServer">
 <property name="ipAddress">192.168.108.103</property>

---仅跟在上面的配置后面,multiPool行(本来就有,修改)
<dbServer name="slaves" virtual="true">
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool #不改
<property name="poolNames">slave1,slave2</property>
</poolConfig> #不改

[root@amoeba ~]# /usr/local/amoeba/bin/amoeba start&
[1] 33499
[root@amoeba ~]# netstat -anpt | grep java
tcp6 0 0 :::8066 :::* LISTEN
33499/java
tcp6 0 0 127.0.0.1:21128 :::* LISTEN
33499/java
tcp6 0 0 192.168.108.110:41754 192.168.108.101:3306 ESTABLISHED
33499/java
tcp6 0 0 192.168.108.110:41722 192.168.108.102:3306 ESTABLISHED
33499/java
tcp6 0 0 192.168.108.110:36956 192.168.108.103:3306 ESTABLISHED
33499/java

测试客户端

bash 复制代码
[root@mysql-client ~]# yum install -y mysql
[root@mysql-client ~]# mysql -u amoeba -p123456 -h 192.168.108.110 -P8066
 #连接amoeba服务器,8086端口在amoeba上执行netstat -anpt|grep java看

在MASTER上

bash 复制代码
[root@mysql-master ~]# mysql -u root -p
Enter password:

mysql> use school;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed

mysql> insert student (name,age)values('鸣人',20);
Query OK, 1 row affected (0.00 sec)


#此时会同步
#mysql-slave01
mysql> select * from student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
+----+--------+------+--------+
2 rows in set (0.00 sec)
#mysql-slave02
mysql> select * from student;
+----+--------+------+--------+
| id | name | age | gender |
+----+--------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
+----+--------+------+--------+
2 rows in set (0.00 sec)

在两台从上关闭,客户端上插入数据,内容不会同步

bash 复制代码
# mysql-slave01
mysql> stop slave;
# mysql-slave02
mysql> stop slave;

#mysql-client上添加,由于不会同步,只有mysql-master192.168.108.101节点有该记录
# mysql-client
MySQL [school]> insert student (name,age)values('卡卡西',30);

#mysql-slave01
mysql> use school;
mysql> insert student (name,age)values('卡卡西',31);

# mysql-slave02
mysql> use school;
mysql> insert student (name,age)values('卡卡西',32);

验证主从复制

在mysql-slave01和mysql-slave02上查看

bash 复制代码
# mysql-slave01
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 31 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
#mysql-slave02
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 32| M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)

并没有将客户端写入的insert student (name,age)values('卡卡西',30);同步

bash 复制代码
# mysql-master
mysql> select * from student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 30 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)

验证读写分离

在客户端上测试,第一次会向从服务器1读数,据-第二次会向从2读取

bash 复制代码
#mysql-client
MySQL [(none)]> select * from school.student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 31 | M |
+----+-----------+------+--------+
3 rows in set (0.02 sec)
MySQL [(none)]> select * from school.student;
+----+-----------+------+--------+
| id | name | age | gender |
+----+-----------+------+--------+
| 10 | 路飞 | 20 | M |
| 11 | 鸣人 | 20 | M |
| 12 | 卡卡西 | 32 | M |
+----+-----------+------+--------+
3 rows in set (0.00 sec)
#都是从从节点读取的,读写分离,由实验结果可知:客户端的读取内容会从mysql-slave01和mysqlslave02上轮询得到。
相关推荐
宁小法1 小时前
mysql - SQLSTATE[23000]报错类型
mysql·23000·报错类型
j_xxx404_2 小时前
MySQL库操作硬核解析:字符集、校验规则、大小写比较、备份恢复与连接排查
运维·服务器·数据库·人工智能·mysql·ai·oracle
minji...2 小时前
MySQL数据库 (五) MySQL表的约束(上),非空约束,默认值约束,零填充约束,主键约束,符合主键
数据库·mysql·表的约束·主键约束·非空约束·复合主键·零填充约束
列星随旋2 小时前
MySQL面经整理
数据库·mysql
是一个Bug3 小时前
MySQL 核心知识梳理:从底层原理到实战优化
mysql
minji...3 小时前
MySQL数据库 (四) MySQL的数据类型,tinyint,float,decimal,枚举enum和集合set
数据库·mysql·tinyint·enum·decimal·varchar·bit
todoitbo4 小时前
从 MySQL 到 KingbaseES:Database、Schema、User 一次讲透
数据库·mysql·国产数据库·kingbasees
千云5 小时前
100w大表0停机回滚:我们为什么放弃Undo Log,选择表名切换?
数据库·后端·mysql
AC赳赳老秦5 小时前
用 OpenClaw 制定技术学习计划:根据目标岗位自动生成学习路线、推荐学习资源
开发语言·c++·人工智能·python·mysql·php·openclaw