文章目录
- MySQL主从复制和读写分离
-
- 一、MySQL主从复制
-
- 1、MySQL主从复制原理
- 2、MySQL主从复制的工作过程
- 3、MySQL的复制类型
-
- [3.1 STATEMENT](#3.1 STATEMENT)
- [3.2 ROW](#3.2 ROW)
- [3.3 MIXED](#3.3 MIXED)
- 4、MySQL主从复制高延迟的原因
- 5、MySQL主从复制高延迟的解决办法
- 6、MySQL主从复制环境配置
- 7、搭建MySQL主从复制
-
- [7.1 主从服务器时间同步](#7.1 主从服务器时间同步)
-
- [7.1.1 主服务器配置](#7.1.1 主服务器配置)
- [7.1.2 从服务器配置](#7.1.2 从服务器配置)
- [7.2 主服务器配置](#7.2 主服务器配置)
- [7.3 从服务器配置](#7.3 从服务器配置)
- [7.4 验证](#7.4 验证)
- 二、MySQL读写分离
-
- 1、MySQL读写分离原理
- 2、MySQL读写分离的原因
- 3、MySQL读写分离的应用
- 4、MySQL主从复制与读写分离
- 5、搭建MySQL读写分离
-
- [5.1 amoeba服务器配置](#5.1 amoeba服务器配置)
- [5.2 配置 amoeba读写分离,两个 slave 读负载均衡](#5.2 配置 amoeba读写分离,两个 slave 读负载均衡)
-
- [5.2.1 先在master、slave1、slave2 的mysql上开放权限给 amoeba 访问](#5.2.1 先在master、slave1、slave2 的mysql上开放权限给 amoeba 访问)
- [5.2.2 再对amoeba服务器进行配置](#5.2.2 再对amoeba服务器进行配置)
- [5.3 客户端服务器测试读写分离](#5.3 客户端服务器测试读写分离)
- [5.4 关闭slave功能,在主从服务器中插入数据](#5.4 关闭slave功能,在主从服务器中插入数据)
- [5.5 关闭slave功能后,客户端写入数据](#5.5 关闭slave功能后,客户端写入数据)
- [5.6 从服务器开启slave功能](#5.6 从服务器开启slave功能)
MySQL主从复制和读写分离
实现高可用,高并发
一、MySQL主从复制
1、MySQL主从复制原理
- 配置主从复制是为了两台设备保持数据完整性,主从复制是slave角色复制master角色的数据
2、MySQL主从复制的工作过程

主从复制的过程
- mysql主数据库将处理的事务(增、删、改、查)存放到二进制日志文件(mysql-bin-000001),通知存储引擎将数据存储到磁盘中
- master的dump线程监听slave的I/O线程的请求,将二进制日志文件更新的数据发送给slave的I/O线程
- slave的工作线程(I/O线程),会将master更新的数据复制存放到slave的中继日志文件中,然后由slave中的sql线程进行读取数据,并将数据存放到自己的二进制(类似)文件中,与master的数据保持一致
主从复制核心内容
-
两个日志文件
- 二进制日志文件(master)
- 中继日志文件(slave)
-
三个线程
- dump线程(master):监听slave的I/O线程请求,将master中二进制日志文件中更新的数据发送给slave的I/O线程
- I/O线程(slave):将更新的数据存放到slave的中继日志文件中
- sql线程(slave):读取中继日志文件中的数据,并将数据存放到自己的二进制(类似)文件中,与master数据保持一致性
3、MySQL的复制类型
3.1 STATEMENT
- 基于语句的复制。
- 在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。
3.2 ROW
- 基于行的复制。
- 把改变的内容复制过去, 而不是把命令在从服务器上执行一遍。
3.3 MIXED
- 混合类型的复制。
- 默认采用基于语句的复制,一旦发现基于语句无法精确复制时, 就会采用基于行的复制。
4、MySQL主从复制高延迟的原因
- master服务器高并发,形成大量事务
- 网络延迟
- 主从硬件设备导致 cpu主频、内存io、硬盘io
- 本来就不是同步复制、而是异步复制
5、MySQL主从复制高延迟的解决办法
- 从库优化Mysql参数。比如增大innodb_buffer_pool_size,让更多操作在Mysql内存中完成,减少磁盘操作。
- 从库使用高性能主机。包括cpu强悍、内存加大。避免使用虚拟云主机,使用物理主机,这样提升了i/o方面性能。
- 从库使用SSD磁盘,避免使用低速的机械硬盘。
- 网络优化,避免跨机房实现同步。
6、MySQL主从复制环境配置
服务器 | 主机名 | IP | 软件版本 |
---|---|---|---|
Master服务器 | master | 192.168.10.11 | mysql 5.7 |
Slave1服务器 | slave1 | 192.168.10.12 | mysql 5.7 |
Slave2服务器 | slave2 | 192.168.10.13 | mysql 5.7 |
Amoeba服务器 | amoeba | 192.168.10.14 | jdk1.6/Amoeba |
客户端服务器 | client | 192.168.10.15 | yum安装mariadb |
7、搭建MySQL主从复制
- 搭建之前先要关闭防火墙和核心防护
mysql
systemctl stop firewalld
systemctl disable firewalld
#关闭防火墙
setenforce 0
#关闭防护中心
7.1 主从服务器时间同步
7.1.1 主服务器配置
mysql
yum install -y ntp
#安装ntp
#修改配置文件
vim /etc/ntp.conf
server 127.127.10.0
#设置本地是时钟源,添加网段
fudge 127.127.10.0 stratum 8
#设置时间层级为8
service ntpd start
#开启服务
service ntpd status
#查看服务状态


7.1.2 从服务器配置
slave1与slave2都需要配置
mysql
yum install -y ntp ntpdate
#安装服务
service ntpd start
#查看服务状态
/usr/sbin/ntpdate 192.168.10.11
#与主服务器保持时间同步


7.2 主服务器配置
mysql
#修改配置文件
vim /etc/my.cnf
server-id=1
#定义server-id,每台主机不可相同
log-bin=master-bin
#添加主服务器开启二进制日志
binlog_format=MIXED
#复制类型使用MIXED模式
log-slave-updates=true
#添加允许从服务器更新二进制日志
server-id=1
log-bin=master-bin
binlog_format=MIXED
log-slave-updates=true
systemctl restart mysqld.service
#重启数据库
mysql -uroot -p
#登录mysql
grant replication slave ON *.* to 'myslave'@'192.168.10.%' identified by '123456';
#设置从服务器账号并授权
flush privileges;
#刷新
show master status;
#查看状态


7.3 从服务器配置
- slave1配置
mysql
#修改配置文件
vim /etc/my.cnf
server-id=2
#修改id与其他主机不能相同
relay-log=relay-log-bin
#开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index
#定义中继日志文件的位置和名称
relay_log_recovery=1
#重新复制时,从最后的中继日志文件开始恢复复制
server-id=2
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
relay_log_recovery=1
systemctl restart mysqld.service
#重启数据库
mysql -uroot -p
#登录mysql
change master to master_host='192.168.10.11',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
#配置同步,注意master_log_file和master_log_pos的值要与Master查询的一致
start slave;
#开动同步,如有报错执行reset slave;
show slave status\G
#查看从服务器状态,确保IO和SQL线程都是Yes,代表同步正常。


- slave2配置
mysql
#修改配置文件
vim /etc/my.cnf
server-id=3
#修改id与其他主机不能相同
relay-log=relay-log-bin
#开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index
#定义中继日志文件的位置和名称
relay_log_recovery=1
#重新复制时,从最后的中继日志文件开始恢复复制
server-id=3
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
relay_log_recovery=1
systemctl restart mysqld.service
#重启数据库
mysql -uroot -p
#登录mysql
change master to master_host='192.168.10.11',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;
#配置同步,注意master_log_file和master_log_pos的值要与Master查询的一致
start slave;
#开动同步,如有报错执行reset slave;
show slave status\G
#查看从服务器状态,确保IO和SQL线程都是Yes,代表同步正常。


一般Slave_IO_Running:No 的可能性有
- 网络不通
- my.cnf配置有问题
- 密码、file文件名、pos偏移量不对
- 防火墙没有关闭
7.4 验证
mysql
create database kgc;
#master服务器创建库,slave服务器中也有新建数据库信息


二、MySQL读写分离
1、MySQL读写分离原理
-
只在主服务器上写,只在从服务器上读
-
主数据库处理事务性查询,从数据库处理SELECT查询
-
数据库复制用于将事务性查询的变更同步到集群中的从数据库
-
读写分离方案
-
基于程序代码内部实现
-
基于中间代理层实现
-
MySQL-Proxy
-
Amoeba
-
-
2、MySQL读写分离的原因
- 因为数据库的"写"(写10000条数据可能要3分钟)操作是比较耗时的。
- 但是数据库的"读"(读10000条数据可能只要5秒钟)。
- 所以读写分离,解决的是,数据库的写入,影响了查询的效率。
3、MySQL读写分离的应用
- 数据库不一定要读写分离, 如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用。
- 利用数据库主从同步, 再通过读写分离可以分担数据库压力,提高性能。
4、MySQL主从复制与读写分离
- 在实际的生产环境中, 对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。有点类似于rsync,但是不同的是rsync是对磁盘文件做备份,而mysql主从复制是对数据库中的数据、语句做备份。
5、搭建MySQL读写分离
5.1 amoeba服务器配置
- 安装Java环境(amoeba仅支持jdk1.6版本)
mysql
cd /opt
#切换目录
cp jdk-6u14-linux-x64.bin /usr/local/
#复制安装包到/usr/local/目录
cd /usr/local
#切换目录
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin
#执行,一直按回车键,出现下列行时,输入yes,再按回车即可
Do you agree to the above license terms? [yes or no]
yes(需要输入)
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/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin
#末行添加上面配置内容
source /etc/profile
#执行
java -version
#查看Java版本




- 安装amoeba
mysql
mkdir /usr/local/amoeba
#新建目录
cd /opt
#切换到有安装包的目录下
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 start|stop,说明安装成功

5.2 配置 amoeba读写分离,两个 slave 读负载均衡
5.2.1 先在master、slave1、slave2 的mysql上开放权限给 amoeba 访问
- master服务器
mysql
grant all on *.* to xxxx@'192.168.10.%' identified by '123456';
#主服务器自定义用户xxxx,并给amoeba开放权限可以访问

- slave服务器
mysql
grant all on *.* to xxxx@'192.168.10.%' identified by '123456';
#从服务器自定义用户xxxx,并给amoeba开放权限可以访问

5.2.2 再对amoeba服务器进行配置
mysql
cd /usr/local/amoeba/conf/
#切换目录
cp amoeba.xml amoeba.xml.bak
#备份配置文件
#修改配置文件
vim amoeba.xml
30 <property name="user">amoeba</property>
#修改30行
32 <property name="password">123456</property>
#修改32行
115 <property name="defaultPool">master</property>
#修改115行
117 <!-- -->
118 <property name="writePool">master</property>
119 <property name="readPool">slaves</property>
120
#取消117行-120行注释,并进行修改
cp dbServers.xml dbServers.xml.bak
#备份配置文件
#修改配置文件
vim dbServers.xml
22 <!-- mysql schema
23 <property name="schema">test</property>
24 -->
#注释掉23行,默认进入test库,防止mysql中没有test库时报错
26 <property name="user">xxxx</property>
#修改26行,使用之前创建的授权用户
28 <!-- mysql password -->
29 <property name="password">123456</property>
30
#取消28行-30行注释,修改密码为之前创建授权用户的密码
45 <dbServer name="master" parent="abstractServer">
#修改45行,主服务器名为master
48 <property name="ipAddress">192.168.10.11</property>
#修改48行,主服务器地址
52 <dbServer name="slave1" parent="abstractServer">
#修改52行,从服务器1名为slave1
55 <property name="ipAddress">192.168.10.12</property>
#修改55行,从服务器1的地址
58 <dbServer name="slave2" parent="abstractServer">
59 <factoryConfig>
60 <!-- mysql ip -->
61 <property name="ipAddress">192.168.10.13</property>
62 </factoryConfig>
63 </dbServer>
#复制上面slave1的6行配置信息,修改58行,从服务器2名为slave2,修改61行,从服务器2的地址
65 <dbServer name="slaves" virtual="true">
#修改65行,slaves
71 <property name="poolNames">slave1,slave2</property>
#修改71行,slave1,slave2
/usr/local/amoeba/bin/amoeba start&
#后台启动amoeba,按ctrl+c返回
ss -natp |grep java
#查看8066端口是否开启,默认端口tcp8066




5.3 客户端服务器测试读写分离
- 客户端服务器(地址:192.168.10.15)
mysql
yum install -y mariadb-server mariadb
#安装
systemctl start mariadb.service
#开启服务
mysql -u amoeba -p123456 -h 192.168.10.14 -P8066
#通过amoeba服务器代理访问mysql,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从服务器。
#这里通过192.168.10.14主机的8066端口使用用户amoeba登录mysql。
show databases;
#查看数据库信息
use luck;
#切换数据库
show tables;
#查看库中表的信息(没有表)
create table luck(id int,name char(10));
#创建表luck
show tables;
#查看库中表的信息,此时luck表存在


- master服务器(地址:192.168.10.11)
mysql
show databases;
#查看数据库信息
use luck;
#切换数据库
show tables;
#查看库中表的信息,master服务器有luck表

- slave1服务器(地址:192.168.10.12)
mysql
show databases;
#查看数据库信息
use luck;
#切换数据库
show tables;
#查看库中表的信息,slave1服务器有luck表

- slave2服务器(地址:192.168.10.13)
mysql
show databases;
#查看数据库信息
use luck;
#切换数据库
show tables;
#查看库中表的信息,slave2服务器有luck表

总结:客户端服务器做出修改,所有服务器数据都会同步
5.4 关闭slave功能,在主从服务器中插入数据
- slave1服务器(地址:192.168.10.12)
mysql
stop slave;
#关闭slave
insert into luck values(1,'slave1');
#在luck表中插入数据
select * from luck;
#查看luck表的数据

- slave2服务器(地址:192.168.10.13)
mysql
stop slave;
#关闭slave
insert into luck values(2,'slave2');
#在luck表中插入数据
select * from luck;
#查看luck表的数据

- master服务器(地址:192.168.10.11)
mysql
insert into luck values(3,'master');
#luck表中插入数据
select * from luck;
#查看luck表信息

- 客户端服务器(192.168.10.15)
mysql
select * from luck;
#客户端查询luck表信息

总结:由于从服务器关闭了slave功能,所以客户端无法查询到master服务器修改的数据,并且客户端以轮询的方式显示slave1与slave2中的数据
5.5 关闭slave功能后,客户端写入数据
- 客户端服务器(地址:192.168.10.15)
mysql
insert into luck values(4,'client');
#在luck表中插入数据
select * from luck;
#客户端以轮询的方式只显示slave1与slave2中的数据

- master服务器(地址:192.168.10.11)
mysql
select * from luck;
#查看luck表中数据,显示客户端与master服务器的数据

- slave1服务器(地址:192.168.10.12)
mysql
select * from luck;
#查询luck表的信息,只会显示本机插入的数据,不会显示客户端插入的数据

- slave2服务器(地址:192.168.10.13)
mysql
select * from luck;
#查询luck表的信息,只会显示本机插入的数据,不会显示客户端插入的数据

总结:客户端服务器的修改操作是对于Master服务器进行的,因此Master服务器上可以看到客户端服务器所做的insert操作。由于客户端服务器的select操作是对从服务器进行的,而从服务器关闭了slave功能,无法获取更新,因此客户端服务器本身以及从服务器都无法查看更新操作。
5.6 从服务器开启slave功能
- slave1服务器(地址:192.168.10.12)
mysql
start slave;
#开启slave功能
select * from luck;
#查看luck表信息,除了slave2的数据不显示,master和客户端的数据都显示

- slave2服务器(地址:192.168.10.13)
mysql
start slave;
#开启slave功能
select * from luck;
#查看luck表信息,除了slave1的数据不显示,master和客户端的数据都显示

- master服务器(地址:192.168.10.11)
mysql
select * from luck;
#查看luck表信息,不会显示从服务器的数据

- 客户端服务器(地址:192.168.10.15)
mysql
select * from luck;
##查看luck表信息,客户端以轮询的方式,显示两个从服务器的内容

总结:从服务器开启slave服务后可以从Master服务器上获取更新,但是从服务器上更新的数据不会被Master服务器看到。
客户端再次插入数据
- 客户端服务器(地址:192.168.10.15)
mysql
insert into luck values(5,'client002');
#在luck表中插入数据
select * from luck;
#查询luck表中数据,客户端以轮询的方式,显示两个从服务器的内容

- master服务器(地址:192.168.10.11)
mysql
select * from luck;
#表中会显示客户端新插入的数据

- slave1服务器(地址:192.168.10.12)
mysql
select * from luck;
#查询luck表的信息,slave1会显示客户端新插入的数据

- slave2服务器(地址:192.168.10.13)
mysql
select * from luck;
#查询luck表的信息,slave2会显示客户端新插入的数据

总结:客户端服务器上的数据修改,会同步到所有服务器中。