1.MySQL主从复制与读写分离
1.1主从复制与读写分离
mysql使用主从复制的原因大概由一下三点:
1、在业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
2、做数据的热备
3、架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
mysql主从复制原理
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,才会提交事务。
主库的事务提交依赖于后面所有的从库,这样一来性能就会明显得下降
除非是对所有从库数据一致性要求非常高的场景,否则我们一般不采用这种策略
全同步复制的数据一致性最好,但是性能也是最差的
mysql主从同步的三种模式_吴小佳同学的博客
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 #登录mysqlmysql> 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.cnfserver-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 -pmysql> 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/profileexport JAVA_HOME=/usr/local/jdk1.6export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/libexport PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATHexport AMOEBA_HOME=/usr/local/amoebaexport PATH=$PATH:$AMOEBA_HOME/bin
[root@amoeba local]# source /etc/profile[root@amoeba local]# java -version2.配置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打开主从复制
可以看到客户端和主之前插入的数据了。
再次打开客户端查看,还是存在两种表记录的情况。
主服务器上还是只有客户端与主插入的数据。