每日分享:
只有超出别人的付出,才会有超出别人的收获。
文章目录
一、主从复制
1、什么是主从复制
MySQL 的主从复制和 MySQL 的读写分离两者有着紧密联系,首先要部署主从复制,
只有主从复制完成了,才能在此基础上进行数据的读写分离。
2、MySQL支持的复制类型
- 基于语句的复制(STATEMENT)。在主服务器上执行的 SQL 语句,在从服务器上执行同样的语句。MySQL 默认采用基于语句的复制,效率比较高。
- 基于行的复制(ROW)。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。
- 混合类型的复制(MIXED)。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
3、主从复制的工作过程
Master节点需要开启二进制日志,Slave节点需要开启中继日志。
- Master 节点将数据的改变记录成二进制日志(bin log) ,当Master上的数据发生改变时(增删改),则将其改变写入二进制日志中。
- Slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/O线程请求Master的二进制事件。(请求二进制数据)
- 同时Master 节点为每个I/O线程启动一个dump线程,用于通知和向其发送二进制事件,I/O线程接收到bin-log内容后,将内容保存至slave节点本地的中继日志(Relay log)中,Slave节点将启动SQL线程从中继日志中读取二进制事件,在本地重放,即解析成sql 语句逐一执行,使得其数据和Master节点的保持一致。最后I/O线程和SQL线程将进入睡眠状态,等待下一次被唤醒。
4、主从复制相关线程
主节点:
- dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events
从节点:
- I/O Thread:向Master请求二进制日志事件,并保存于中继日志中
- SQL Thread:从中继日志中读取日志事件,在本地完成重放
5、跟复制功能相关的文件
-
master.info: 用于保存slave连接至master时的相关信息,例如账号、密码、服务器地址等
-
relay-log.info: 保存在当前slave节点上已经复制的当前二进制日志和本地relay log日志的对应关系
-
mariadb-relay-bin.00000#: 中继日志,保存从主节点复制过来的二进制日志,本质就是二进制日志
6、 MySQL 主从复制延迟
-
master服务器高并发,形成大量事务
-
网络延迟
-
主从硬件设备导致 CPU主频、内存IO、硬盘IO
-
本来就不是同步复制、而是异步复制
二、MySQL读写分离原理
1、什么是读写分离
- 让主数据库处理事务性增、改、删操作( INSERT、UPDATE、DELETE) ,而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
2、读写分离存在意义
- 因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的。
- 但是数据库的“读”(读10000条数据可能只要5秒钟)。
- 所以读写分离,解决的是,数据库的写入,影响了查询的效率
3、常见的 MySQL 读写分离分为两种
基于程序代码内部实现
- 在代码中根据select、insert进行路由分类,这类方法也是目前生产环境应用最广泛的。
- 优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
- 但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大。
基于中间代理层实现
代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序。
- MySQL-Proxy。MySQL-Proxy为MysQL开源项目,通过其自带的1ua脚本进行sQL判断。
- Atlas。是由奇虎360的Web平台部基础架构团队开发维护的一个基于MysQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用atlas运行的mysql业务,每天承载的读写请求数达几干保条。支持事物以及存储过程。
- Amoeba。由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。
- Mycat。是一款流行的基于Java语言编写的数据库中间件,是一个实现了MySq1协议的服务器,其核心功能是分库分表。配合数据库的主从模式还可以实现读写分离。
- 由于使用MysQLProxy需要写大量的ua脚本,这些Lua并不是现成的,而是需要自己去写。这对于并不熟悉MysQLProxy 内置变量和MySQL Protocol的人来说是非常困难的。
- Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层。
三、主从复制案例演示(异步复制)
实验准备
master 服务器:20.0.0.12,mysql5.7
slave1 服务器:20.0.0.6,mysql5.7
slave2 服务器:20.0.0.5,mysql5.7
##关闭防火墙
systemctl disable --now firewalld
setenforce 0
1、主服务器使用本地时钟源
yum install -y ntp
##修改配置文件
vim /etc/ntp.conf
server 127.127.72.0 #设置本地时钟源,注意修改网段(72是网段)
fudge 127.127.72.0 stratum 8 #设置时间层级为8(限制在15以内)
systemctl start ntpd
yum install -y ntp
systemctl start ntpd
/usr/sbin/ntpdate 20.0.0.12
crontab -e
*/30 * * * * /usr/sbin/ntpdate 20.0.0.12
2、主服务器的mysql配置
vim /etc/my.cnf
log-bin=mysql-bin
binlog_format = MIXED
log-slave-updates=true
expire_logs_days = 7
max_binlog_size = 500M
##保存退出
systemctl restart mysqld.service
mysql -u root -p
grant replication slave on *.* to 'myslave'@'20.0.0.%' identified by '123123'; flush privileges;
show master status;
3、从服务器1的mysql配置
vim /etc/my.cnf
server-id = 2
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
##重启服务
systemctl restart mysqld
mysql -u root -p
change master to master_host='20.0.0.12',master_user='myslave',master_password='123123',master_log_file='mysql-bin.000001',master_log_pos=599;
start slave;
show slave status\G
4、从服务器2的mysql配置
vim /etc/my.cnf
server-id = 3
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
##重启服务
systemctl restart mysqld
mysql -u root -p
change master to master_host='20.0.0.12',master_user='myslave',master_password='123123',master_log_file='mysql-bin.000001',master_log_pos=599;
start slave;
show slave status\G
配置大致相同,就是server-id要和master服务器和salver1不同
5、验证主从复制效果
##主服务器上进入执行
create database school;
##去从服务器上查看是否同步成功
show databases;
四、搭建 MySQL 读写分离
实验准备
Master 服务器:20.0.0.12,mysql5.7
Slave1 服务器:20.0.0.6,mysql5.7
Slave2 服务器:20.0.0.5,mysql5.7
Amoeba 服务器:20.0.0.7,jdk1.6、Amoeba centos7-3
客户端:20.0.0.4,mysql5.7
1、安装Java环境
Amoeba 是基于 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。
cd /opt/
##上传文件
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin
mv jdk1.6.0_14/ /usr/local/jdk1.6
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
##执行全局配置文件
source /etc/profile
java -version
2、安装 Amoeba软件
cd /opt/
##上传压缩包并解压
mkdir /usr/local/amoeba
tar zxvf /opt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
3、配置 Amoeba读写分离,两个 Slave 读负载均衡
##在master、slave1、slave2 的mysql上开放权限给 Amoeba 访问
grant all on *.* to test@'20.0.0.%' identified by '123123';
##再回到amoeba服务器配置amoeba服务
cd /usr/local/amoeba/conf/
#备份配置文件,修改amoeba配置文件
[root@Amo conf]# cp amoeba.xml amoeba.xml.bak
[root@Amo conf]# vim amoeba.xml
--30行--
<property name="user">amoeba</property> #30行和32行,授权客户端用于登录amoeba的账号和密码
--32行--
<property name="password">123456</property>
--115行--
<property name="defaultPool">master</property> #设置默认服务器池
--117-去掉注释-
<property name="writePool">master</property> #定义写的服务器池名称
<property name="readPool">slaves</property> #定义读的服务器池名称
#备份数据库配置文件,之后修改数据库配置文件dbServers.xml
cd /usr/local/amoeba/conf/
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml
--23行--注释掉 作用:默认进入test库,注释掉以防mysql中没有test库时,会报错
<!-- <property name="schema">test</property> -->
##26-30行,此用户就是之前在3台主从服务器上授权的用户,授权amoeba服务器用来登录mysql数据库的用户和密码。
--26行--修改
<property name="user">test</property>
--28-30行--去掉注释
<property name="password">123123</property>
--45行--修改,设置主服务器的名称master和地址
<dbServer name="master" parent="abstractServer">
--48行--修改,设置主服务器的地址
<property name="ipAddress">20.0.0.12</property>
--52行--修改,设置从服务器1的名称slave1
<dbServer name="slave1" parent="abstractServer">
--55行--修改,设置从服务器1的地址
<property name="ipAddress">20.0.0.6</property>
--58行--复制上面6行粘贴,设置从服务器2的名称slave2和地址
<dbServer name="slave2" parent="abstractServer">
<property name="ipAddress">20.0.0.5</property>
--65行--修改
<dbServer name="slaves" virtual="true">
--71行--修改
<property name="poolNames">slave1,slave2</property>
/usr/local/amoeba/bin/amoeba start & #后台启动Amoeba软件
netstat -anpt | grep java #查看8066端口是否开启
4、测试读写分离
##客户端
yum install -y mariadb-server mariadb #安装mariadb数据库
systemctl start mariadb.service #启动mariadb
mysql -u amoeba -p123123 -h 20.0.0.7 -P8066
##在主服务器服务器上新建表
use test;
create table info(id int(10),name char(40));
show tables;
##在客户机上,插入数据会同步到所有数据库中
use test;
insert into info values(1,'小明');
##在主从服务器上查看
##测试读写分离
##停止slave1和slave2的slave同步功能
stop slave;
##在master、slave1和slave2上插入数据