Mysql主从复制与读写分离

MySQL主从复制

客户端往主服务器插入一条数据(库、表、表中的数据),主服务器将新增的记录同步到两个从服务器

主从复制的模式

1、异步复制(Asynchronous replication)
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给客户端,
并不关心从库是否已经接收并处理,这样就会有一个问题,主如果崩溃掉了,
此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,
可能导致新主上的数据不完整。

2、全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。
因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
(对数据一致性、完整性要求很高的场景)

3、半同步复制(Semisynchronous replication)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,
而是等待至少一个从库接收到并写到relay log中才返回给客户端。
相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,
这个延迟最少是一个TCP/IP往返的时间。(RTT:round-trip time)
所以,半同步复制最好在低延时的网络中使用。

Mysql主从复制与读写分离_第1张图片

实现异步复制

实验配置:
20.0.0.81:主Mysql
20.0.0.82:从MYsql1
20.0.0.83:从Mysql2

1.关闭防火墙

81、82、83相同操作:
systemctl stop firewalld
setenforce 0

2.Mysql主从服务器时间同步

主服务器设置

81:
yum -y install ntp
vim /etc/ntp.conf
--添加--
server 127.127.0.0  #设置本地是时钟源,注意修改网段
fudge 127.127.0.0 stratum 8  #设置时间层级为8,数字越小,时间精确度越高(限制在15内)

systemctl restart ntpd

从服务器设置

82、83相同操作:
yum -y install ntp
systemctl restart ntpd
/usr/sbin/ntpdate 20.0.0.81
crontab -e -u root
--添加--
*/30 * * * * /usr/sbin/ntpdate 20.0.0.81

时间同步验证

3.主服务器的Mysql配置

vim /etc/my.cnf
--添加--
log-bin=master-bin  #主服务器开启二进制日志
binlog_format=MIXED
log-slave-updates=true  #添加,允许slave从master复制数据时可以写入到自己的二进制日志

systemctl restart mysqld
mysql -u root -p123456
grant replication slave on *.* to 'myslave'@'20.0.0.%' identified by '123456';
flush privileges;
show master status;

Mysql主从复制与读写分离_第2张图片

4.从服务器的Mysql配置

82:
vim /etc/my.cnf
--添加--
server-id = 2
relay-log=relay-log-bin
#指定了从服务器上中继日志的基本文件名。中继日志的文件名将以 "relay-log-bin" 开头。					
relay-log-index=slave-relay-bin.index
#指定了中继日志索引文件的名称。中继日志索引文件用于记录中继日志文件的顺序和位置。
relay_log_recovery=1
#默认是0
#1表示开启中继日志的恢复,如果从服务器出现异常或者崩溃时,
从服务器会从主服务器的二进制日志正确读取和应用中继日志(为了同步)。

systemctl restart mysqld

83:
vim /etc/my.cnf
--添加--
server-id = 3
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
relay_log_recovery=1

systemctl restart mysqld
82、83相同操作:
mysql -u root -p123456
CHANGE master to master_host='20.0.0.81',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=599;
#配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致
start slave;  #启动同步,如有报错执行 reset slave;
show slave status\G;  #确保 IO 和 SQL 线程都是 Yes,代表同步正常

Mysql主从复制与读写分离_第3张图片

负责和主库的IO通信如果是'NO':

  • 1、网络问题,查看主机之间是否能ping通
  • 2、my.cnf 配置文件错误
  • 3、change命令配置同步时,可能是文件名错误,或者是位置偏移量错误
  • 4、防火墙和安全机制的问题

5.验证主从复制效果

主服务器新建库

Mysql主从复制与读写分离_第4张图片

主服务器创建数据库:
create database test;

Mysql主从复制与读写分离_第5张图片

主服务器新建表

主服务器新建表:
create table info(
name varchar(10)
);

Mysql主从复制与读写分离_第6张图片

主服务器表中插入数据

向主服务器的表info中插入一条数据

Mysql主从复制与读写分离_第7张图片

Mysql主从复制与读写分离_第8张图片

从服务器新建库

从服务器1新建库:
create database test1;

Mysql主从复制与读写分离_第9张图片

6.异步复制小结

1、主从复制是单向的,只能从主复制到从

2、主从复制出现延迟可能的原因:

  • 网络延迟
  • 主从硬件设备(cpu主频、内存IO、硬件IO)
  • 使用的是同步复制而不是异步复制

解决方法:

硬件方面:主库一般来说不需要动得太多,从库得硬件配置要更好。
提升随机写的性能、硬盘可以换成固态的,升级cpu的核数、扩展内存、尽量使用物理机(不适用云服务器)。

网络层面:主从服务器都配置在一个局域网内,尽量避免跨网段和跨机房。

架构方面:做读写分离,把写入控制在主库,从库负责读,降低从库的压力。

配置方面:Mysql配置,从配置文件的角度实现性能最大化。

追求安全性的配置:

修改innodb_flush_log_at_trx_commit=1
#每次事务提交时都会刷新日志以确保持久性,最高级别的数据安全性,但是会影响性能,默认就是1。
#0:即事务提交时不会立刻刷新,而是每秒刷新一次。可以提高性能,但是发生故障会导致数据丢失。
#2:事务提交时,事务日志不会写入硬盘而是保存在系统缓存,不会进行刷新。有一定的安全性和性能,内存要求比较高。

修改sync_binlog=1
#1(默认值):每次提交事务之后,直接把二进制日志刷新到磁盘,以确保日志的持久性,会占用比较高的性能,但是安全性高。
#0:将二进制日志写入缓存,也不会刷新日志。故障发生也会丢失数据,内存的要求也提高了。
#N:每N次事务提交后执行一次刷新到磁盘,可以提高性能,但是一旦崩溃,数据会大量丢失。

追求性能最大化的配置:

修改sync_binlog=0 innodb_flush_log_at_trx_commit=2 log-slave-updates=0
#从库的更新不会写入二进制日志(不建议)

修改innodb_buffer_pool_size 300M 500G
#控制innodb存储引擎的缓冲池大小,设置的数值越高,可以提高innodb的性能。
#更多的数据和索引都可以缓存在内存中,减少磁盘的访问次数,对系统内存要求比较高。

3、主从复制的工作过程
1.主节点的数据记录发生变化都会记录在二进制日志。
2.slave节点会一定时间内对主库的二进制日志义件进行探测,看其是否发生变化,如果变化,从库会开启一个I/O的线程请求的主库的二进制事件。
3.主库会给每一个I/O的线程启动一个dump,用于发送二进制事件给从库,从库通过I/O线程获取更新,save_sq负责将更新写入到从库本地。实现主从一致。

4、主从复制的问题
1.只能在主库上发生变化,然后同步到从。
2.复制过程是串行化过程,在从库上复制是串行的,主库的并行更新不能在从库上并行操作。
3.主从复制的设计目的就是为在主库上写,在从库上查。读写分离,实现高可用。

实现全同步复制

实验配置:
20.0.0.81:服务器1
20.0.0.82:服务器2

1.关闭防火墙

81、82:
systemctl stop firewalld
setenforce 0

2.主服务器1的Mysql配置

hostname master1
su
vim /etc/my.cnf
--
server-id=11    
log-bin=mysql-bin  
auto_increment_increment=2  
auto_increment_offset=1
replicate-do-db=demo_db
--
systemctl restart mysqld
mysql -u root -p123456

create user 'master1'@'%' identified with mysql_native_password by '123456';
grant replication slave on *.* to 'master1'@'%';
flush privileges;
show grants for 'master1'@'%';
show master status;

Mysql主从复制与读写分离_第10张图片

3.主服务器2的Mysql配置

hostname master2
su
vim /etc/my.cnf
--
server-id=12
log-bin=mysql-bin
auto_increment_increment=2
auto_increment_offset=2
replicate-do-db=demo_db
--
systemctl restart mysqld
mysql -uroot -p123456

mysql> change master to master_host='20.0.0.81',
    -> master_user='master1',
    -> master_password='123456',
    -> master_log_file='mysql-bin.000001',
    -> master_log_pos=768;

start slave;
show slave status \G;

Mysql主从复制与读写分离_第11张图片

create user 'master2'@'%' identified with mysql_native_password by '123456';
grant replication slave on *.* to 'master2'@'%';
flush privileges;
show master status;

Mysql主从复制与读写分离_第12张图片

回到主服务器1:
mysql> change master to master_host='20.0.0.82',
    -> master_user='master2',
    -> master_password='123456',
    -> master_log_file='mysql-bin.000001',
    -> master_log_pos=768;

start slave;
show slave status \G;

Mysql主从复制与读写分离_第13张图片

4.验证复制效果

主服务器1新建库:
create database demo_db;

Mysql主从复制与读写分离_第14张图片

主服务器2使用此库新建表:
mysql> use demo_db;
Database changed
mysql> create table info(name char(5));

Mysql主从复制与读写分离_第15张图片

Amobe实现MySQL读写分离

读写分离概述

前提:
要实现读写分离,必须要先实现主从复制。

读写分离:
所有的写入操作都在主,从库只负责读(select)。
如果有更新,是从主库复制到从库。
在工作当中,数据库的读写不会在同一个库中完成。这样既不安全也不能满足高可用,也不能实现高并发。工作中都会做读写分离。

需要读写分离的原因:
数据库在写入数据时,比较耗时(Mysql写一万条数据大概三分钟)
数据库在读取数据时,速度很快(Mysql读一万条数据大概五秒左右)
读写分离之后,数据的写入和读取是分开的,哪怕写入的数据量比较大,但是不影响查询的效率

读写分离适用场景:
某些程序在使用数据库过程中,更新少,但是查询多时,可以考虑读写分离
读和查的需求差不多,也可以考虑读写分离
生产库一般都会做读写分离,测试库一般不管

Mysql读写分离的原理:
1、根据脚本实现,在代码中实现路由分类。
对select、insert进行路由分类,这种方式是最多的。
优点:性能好,在代码中就可以实现,不需要额外的硬件设备。
缺点:开发实现,与运维无关。如果是大型的复杂的应用,设计改动的代码非常多。

2、基于中间代理层实现
Mysql-proxy自带的开源项目,基于自带的lua脚本。
这些lua脚本不是现成的,要自己写,不熟悉内置变量可能无法实现。
atlas、360内部做自己使用的代理工具。每天的读写请求承载量可以到几十亿条。支持事务,支持存储过程。
用amoeba实现读写分离,基于java开发的一个开源软件,不支持事务,也不支持存储过程。但是amoeba还是使用最多、功能比较强大的软件。

实现读写分离

实验配置:
20.0.0.81:主Mysql
20.0.0.82:从MYsql1
20.0.0.83:从Mysql2
20.0.0.10:Amoeba服务器
20.0.0.20:客户端服务器

1.安装 Java 环境

Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。

10:
systemctl stop firewalld
setenforce 0
cd /opt/
--拖入Amoeba安装包和jdk包--
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin
//按yes,按enter
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

2.安装 Amoeba软件

cd /opt
mkdir /usr/local/amoeba
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说明安装成功

3.修改Amoeba配置文件

在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问
81、82、83相同操作:
mysql -u root -p123456
grant all on *.* to amoeba@'20.0.0.%' identified by '123456';
flush privileges;
回到amoeba服务器配置amoeba服务
10:
cd /usr/local/amoeba/conf/
cp amoeba.xml amoeba.xml.bak
vim amoeba.xml
--30--修改
amoeba

--32--修改
123456

--115--修改
master

--117--去掉注释
master
slaves

cp dbServers.xml dbServers.xml.bak

vim dbServers.xml
--23--注释掉  #默认进入test库,以防mysql中没有test库时,会报错


--26--修改
amoeba

--28-30--去掉注释
123456

--45--修改,设置主服务器的名Master


--48--修改,设置主服务器的地址
20.0.0.81

--52--修改,设置从服务器的名slave1


--55--修改,设置从服务器1的地址
20.0.0.82

--58--复制上面6行粘贴,设置从服务器2的名slave2和地址

20.0.0.83

--65行--修改


--71行--修改
slave1,slave2

/usr/local/amoeba/bin/amoeba start &  #启动Amoeba软件,按ctrl+c 返回
netstat -anpt | grep java

Mysql主从复制与读写分离_第16张图片

4.测试读写分离

客户端20:
yum install -y mariadb-server mariadb
systemctl start mariadb.service

在主从服务器上开启查询日志
81、82、83相同操作:
vim /etc/my.cnf
--添加--
general_log=ON
general_log_file=/usr/local/mysql/data/mysql_general.log

systemctl restart mysqld
在客户端服务器上测试
81、82、83打开日志:
tail -f /usr/local/mysql/data/mysql_general.log
客户端20:
mysql -u amoeba -p123456 -h20.0.0.10 -P8066
show databases;
use test;
show tables;
insert into info values('carrot');

20:
select * from info;

Mycat实现MySQL读写分离

Mycat概述

  • 一个彻底开源的,面向企业应用开发的大数据库集群
  • 支持事务、ACID、可以替代MySQL的加强版数据库
  • 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群
  • 一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server
  • 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
  • 一个新颖的数据库中间件产品

实现读写分离

实验配置:
20.0.0.81:主Mysql
20.0.0.82:从MYsql1
20.0.0.10:mycat服务器
20.0.0.20:客户端服务器

1.初始化环境

systemctl stop firewalld
setenforce 0

2.部署主从复制

主Mysql服务器配置:
vim /etc/my.cnf

server-id = 1
log-bin=master-bin
binlog_format=MIXED
log-slave-updates=true

systemctl restart mysqld
mysql -u root -p123456
grant replication slave on *.* to 'myslave'@'20.0.0.%' identified by '123456';
#建立一个myslave用户,允许20.0.0.%这个网段的地址来登录,密码是123456,待会在slave上使用这个账号
flush privileges;
show master status;

Mysql主从复制与读写分离_第17张图片

从Mysql服务器配置:
82:
vim /etc/my.cnf
--添加--
server-id = 2
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index

systemctl restart mysqld

mysql -uroot -p123456
change master to master_host='20.0.0.81',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=599;
start slave;
show slave status \G;

Mysql主从复制与读写分离_第18张图片

3.验证主从复制

主服务器创建数据库:
create database test;

Mysql主从复制与读写分离_第19张图片

4.安装Mycat

10:
#主机上安装java(mycat基于java)
yum install java -y
java -version  #确认安装成功
openjdk version "1.8.0_382"
OpenJDK Runtime Environment (build 1.8.0_382-b05)
OpenJDK 64-Bit Server VM (build 25.382-b05, mixed mode)

#切换至opt目录,下载mycat安装包
cd /opt
wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz

#创建/apps文件夹,并解压mycat包至/apps下
mkdir /apps
tar zxvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /apps/

#设置变量环境
echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh
source /etc/profile.d/mycat.sh

#启动mycat,查看日志文件,最后可以看到启动成功
mycat start
Starting Mycat-server...
tail -f /apps/mycat/logs/wrapper.log

#客户端连接数据库
20:
yum install -y mariadb-server mariadb
systemctl start mariadb.service
mysql -uroot -p123456 -h 20.0.0.10 -P8066

Mysql主从复制与读写分离_第20张图片 Mysql主从复制与读写分离_第21张图片

5.修改Mycat配置文件

10:
vim /apps/mycat/conf/server.xml
--44去掉注释,对应的行末注释在51--
--50删除--
5 * 60 * 1000L;
--45修改端口号--
45 3306

Mysql主从复制与读写分离_第22张图片

vim /apps/mycat/conf/schema.xml
--删除所有并添加--



        
        
        
                select user()
                
                 

                
        

Mysql主从复制与读写分离_第23张图片

6.主服务器上授权

81:
mysql -uroot -p123456
GRANT ALL ON *.* TO 'root'@'20.0.0.%' IDENTIFIED BY '123456';
#查看创建成功
use mysql;
select user,host from user;

Mysql主从复制与读写分离_第24张图片

7.重启mycat服务,客户机连接mycat

10:
#在mycat服务器上,重启mycat服务,查看启动日志,文末出现successfully
mycat restart
tail -f /apps/mycat/logs/wrapper.log

Mysql主从复制与读写分离_第25张图片

#查看3306端口
ss -antp|grep 3306

Mysql主从复制与读写分离_第26张图片

#在客户机上登录mycat
mysql -uroot -p123456 -h 20.0.0.10
show databases;
use TESTDB;
show tables;

Mysql主从复制与读写分离_第27张图片

8.客户端测试读写分离

#主从服务器上都打开通用日志
81、82、83相同操作:
mysql -uroot -p123456
set global general_log=1;
show variables like 'general%';

#在主从服务器上实时查看通用日志
81:tail -f /usr/local/mysql/data/mysql1.log
82:tail -f /usr/local/mysql/data/mysql2.log

Mysql主从复制与读写分离_第28张图片

客户机新建表格:
create table info(name char(5));

Mysql主从复制与读写分离_第29张图片

Mysql主从复制与读写分离_第30张图片

客户机查看表:
select * from info;

Mysql主从复制与读写分离_第31张图片

Mysql主从复制与读写分离_第32张图片

总结

1.主从复制的原理(重点)

2.读写分离的实现方式

  • 脚本
  • amoeba实现
  • mycat实现

3.如何查看主从复制是否成功

方式1:

从服务器:
mysql -u root -p123456
show salve status\G;

此两项都是yes即是成功

方式2:

在主库创建一个库或者表或者在表中插入数据,看是否能同步到从库

4.IO线程不是yes

异步复制小结中有写

5.show slave status\G;能看到的信息有哪些

  • IO和sql的线程状态信息
  • master服务器的ip地址、端口、事务开始的位置点
  • 最近一次的错误信息和错误的位置
  • 最近一次的IO的报错信息
  • 最近一次的sql的报错信息

6.主从复制延迟怎么解决?

安全性更重要,需斟酌考虑

你可能感兴趣的:(mysql,数据库)