Mysql-主从复制与读写分离
1.MySQL主从复制与读写分离
1.1主从复制与读写分离
mysql使用主从复制的原因大概由一下三点:
1、在业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
2、做数据的热备
3、架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
1.2 主从复制的过程
在主从复制过程中涉及到总共3个线程,两个日志
Master 二进制日志
SLAVE I/O线程
Master dump线程
SLAVE 中继日志
SLAVE SQL线程
(1) Master节点将数据的改变记录成二进制日志(bin log),当Master上的数据发生改变时,则将其改变写入二进制日志中。
(2)Slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/o线程请求Master的二进制事件。
(3)同时Master 节点为每个I/o线程启动一个dump线程,用于向其发送二进制事件,并保存至slave节点本地的中继日志(Relay log)中,Slave节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,即解析成sql语句逐一执行,使得其数据和Master节点的保持一致,最后I/0线程和SQL线程将进入睡眠状态,等待下一次被唤醒。
半同步模式:注意:5.7版本主多了一个ACK_collection线程接受从的ack确认信息
1.3主从复制的同步模式
1.3.1 异步复制:
异步复制是mysql 默认的同步方式
在master为slave开通账号密码、ip授权之后,slave 可以从master进行数据同步,主要依赖的是master的binlog日志
slave会启动两个线程,IO Thread 和 SQL Thread
IO Thread 负责从master拉取binlog 日志,并写入relay中继日志
SQL Thread 负责将relay中继日志中的变更进行重放,更新数据来达到跟master保持数据一致的目的
这个过程中,slave通过IO线程拉取binlog,master无需关注是否有slave需要同步,只做自己的事情,整个复制过程都是异步完成的,这个就是异步复制
异步复制的优势是性能好,缺点是数据的安全性比较差
在某一刻主从之间的数据差异可能较大,主机挂掉之后从机接管,可能会丢失一部分数据。
1.3.2半同步复制
master更新操作写入binlog之后会主动通知slave,slave接收到之后写入relay log 即可应答,master只要收到至少一个ack应答,则会提交事务
可以发现,相比较于异步复制,半同步复制需要依赖至少一个slave将binlog写入relay log,在性能上有所降低,但是可以保证至少有一个从库跟master的数据是一致的,数据的安全性提高。
对于数据一致性要求高的场景,可以采用半同步复制的同步策略,比如主库挂掉时,准备接管的那一个从库,对数据的一致性要求很比较高。
半同步复制的优点是数据的安全性好,缺点是性能比异步复制稍低
1.3.3 全同步复制
全同步复制跟半同步复制的区别是,全同步复制必须收到所有从库的ack,才会提交事务。
主库的事务提交依赖于后面所有的从库,这样一来性能就会明显得下降
除非是对所有从库数据一致性要求非常高的场景,否则我们一般不采用这种策略
全同步复制的数据一致性最好,但是性能也是最差的
2.实验步骤
2.1主从复制配置
环境:centos7
mysql版本:5.7.37
mysql主节点:192.168.80.20
mysql从节点1:192.168.80.25
mysql从节点2:192.168.80.30
mysql主节点设置
1.ntp服务配置 [root@mysql_master ~]# yum install ntp -y ······ [root@mysql_master ~]# vim /etc/ntp.conf --末尾添加-- server 127.0.0.1 #设置本地是时钟源,注意修改网段,127.0.0.1是本地回环地址(127.网段中所有ip实际上都是本地回环地址) fudge 127.0.0.1 stratum 8 #设置时间层级为8(限制在15内) -------------------------------------------------------------- 2.mysql配置文件 [root@mysql_master ~]# vim /etc/my.cnf [mysqld] ...... server-id = 1 log-bin=mysql-bin #添加,主服务器开启二进制日志 binlog_format = MIXED log-slave-updates=true #添加,允许slave从master复制数据时可以写入到自己的二进制日志 expire_logs_days = 7 #设置二进制日志文件过期时间,默认值为0,表示logs不过期 max_binlog_size = 500M #设置二进制日志限制大小,如果超出给定值,日志就会发生滚动,默认值是1GB :wq -------------------------------------------------------------- [root@mysql_master ~]# systemctl restart mysqld #重启msyql服务,使配置生效 [root@mysql_master ~]# mysql -uroot -p #登录mysql mysql> GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.80.%' IDENTIFIED BY '123456'; #从服务授权 mysql> FLUSH PRIVILEGES; mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 603 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.01 sec) #File 列显示日志名,Position 列显示偏移量
mysql从节点1配置
1.ntp配置 [root@mysql_slave1 ~]# yum install ntp ntpdate -y [root@mysql_slave1 ~]# service ntpd start [root@mysql_slave1 ~]# /usr/sbin/ntpdate 192.168.80.20 #与主节点进行时间同步 [root@mysql_slave1 ~]# crontab -e */30 * * * * /usr/sbin/ntpdate 192.168.80.20 -------------------------------------------------------------- 2.mysql配置 [root@mysql_slave1 ~]# vim /etc/my.cnf server-id = 25 #修改,注意id与Master的不同,两个Slave的id也要不同 relay-log=relay-log-bin #添加,开启中继日志,从主服务器上同步日志文件记录到本地 relay-log-index=slave-relay-bin.index #添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录 relay_log_recovery = 1 #选配项 #当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了 relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。 :wq -------------------------------------------------------------- [root@mysql_slave1 ~]# systemctl restart mysqld [root@mysql_slave1 ~]# mysql -uroot -p mysql> CHANGE master to master_host='192.168.80.20',master_user='myslave',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=603; #日志名称与偏移点应该与主status中的相同 mysql> start slave; mysql> show slave status/G # 查看从状态 //确保 IO 和 SQL 线程都是 Yes,代表同步正常。 Slave_IO_Running: Yes #负责与主机的io通信 Slave_SQL_Running: Yes #负责自己的slave mysql进程 #一般 Slave_IO_Running: No/CONNECTING 的可能性: 1、网络不通 2、my.cnf配置有问题 3、密码、file文件名、pos偏移量不对 4、防火墙没有关闭
mysql从节点2配置需要修改server-id
实验截图
主节点配置
1.ntp服务相关配置
2.mysql配置文件
[mysqld]下加入
mysql从节点配置:
1.ntp时间同步设置
2.mysql配置
主从复制效果验证:
2.2 读写分离配置
环境:centos7
mysql版本:5.7.37
mysql主节点:192.168.80.20
mysql从节点1:192.168.80.25
mysql从节点2:192.168.80.30
Amoeba 服务器:192.168.80.35 jdk1.6、Amoeba
Amoeba服务器配置
实现准备jdk和amoeba包至opt目录 1.配置java环境 [root@amoeba opt]# cd /opt [root@amoeba opt]# cp jdk-6u14-linux-x64.bin /usr/local/ [root@amoeba opt]# cd /usr/local/ [root@amoeba opt]# chmod +x jdk-6u14-linux-x64 [root@amoeba opt]# ./jdk-6u14-linux-x64.bin //按yes,按enter [root@amoeba local]# mv jdk1.6.0_14/ /usr/local/jdk1.6 [root@amoeba local]# vim /etc/profile export JAVA_HOME=/usr/local/jdk1.6 export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH export AMOEBA_HOME=/usr/local/amoeba export PATH=$PATH:$AMOEBA_HOME/bin [root@amoeba local]# source /etc/profile [root@amoeba local]# java -version 2.配置Amoeba [root@amoeba local]# cd /opt [root@amoeba opt]# mkdir /usr/local/amoeba [root@amoeba opt]# tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ [root@amoeba opt]# chmod -R 755 /usr/local/amoeba/ [root@amoeba opt]# /usr/local/amoeba/bin/amoeba ##配置 Amoeba读写分离,两个 Slave 读负载均衡## 先将一主两从开放授权 grant all on *.* to test@'192.168.80.%' identified by '123.com'; #再回到amoeba服务器配置amoeba服务: [root@amoeba opt]# cd /usr/local/amoeba/conf/ [root@amoeba opt]# cp amoeba.xml amoeba.xml.bak [root@amoeba opt]# vim amoeba.xml --30行-- <property name="user">amoeba</property> --32行-- <property name="password">123456</property> --115行-- <property name="defaultPool">master</property> --117-去掉注释- <property name="writePool">master</property> <property name="readPool">slaves</property> :wq -------------------------------------------------------------- [root@amoeba opt]# cp dbServers.xml dbServers.xml.bak [root@amoeba opt]# vim dbServers.xml --23行--注释掉 作用:默认进入test库 以防mysql中没有test库时,会报错 <!-- <property name="schema">test</property> --> --26--修改 <property name="user">test</property> --28-30--去掉注释 <property name="password">123.com</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> [root@amoeba opt]# /usr/local/amoeba/bin/amoeba start& 后台启动amoeba [root@amoeba opt]# netstat -anpt | grep java
实验截图
1.配置java环境
2.配置amoeba
先配置mysql一主两从开放授权
grant all on *.* to test@'192.168.80.%' identified by '123.com';
读写分离测试
主机通过Navicat连接数据库
主服务器上创建表
从1从2关闭主从复制
在slave1插入数据
在slave2插入数据
在master插入数据
Navicat查看表数据
关闭表刷新一次,在打开表test
插入一条数据
主查看数据
从1查看数据
从2查看数据
只有主能查看到插入的数据。
从2打开主从复制
可以看到客户端和主之前插入的数据了。
再次打开客户端查看,还是存在两种表记录的情况。
主服务器上还是只有客户端与主插入的数据。