MySQL主从复制原理(原理+实操)

1、MySQL主从复制原理(原理+实操)

主从复制简介

在实际的生产中,为了解决Mysql的单点故障已经提高MySQL的整体服务性能,一般都会采用「主从复制」。

比如:在复杂的业务系统中,有一句sql执行后导致锁表,并且这条sql的的执行时间有比较长,那么此sql执行的期间导致服务不可用,这样就会严重影响用户的体验度。

主从复制中分为「主服务器(master)「和」从服务器(slave)」,「主服务器负责写,而从服务器负责读」,Mysql的主从复制的过程是一个「异步的过程」。

这样读写分离的过程能够是整体的服务性能提高,即使写操作时间比较长,也不影响读操作的进行。

主从复制的原理

首先放一张Mysql主从复制的原理图,总的来说Mysql的主从复制原理还是比较好理解的,原理非常的简单。
MySQL主从复制原理(原理+实操)_第1张图片
Mysql的主从复制中主要有三个线程:master(binlog dump thread)、slave(I/O thread 、SQL thread),Master一条线程和Slave中的两条线程。

master(binlog dump thread)主要负责Master库中有数据更新的时候,会按照binlog格式,将更新的事件类型写入到主库的binlog文件中。

并且,Master会创建log dump线程通知Slave主库中存在数据更新,这就是为什么主库的binlog日志一定要开启的原因。

I/O thread线程在Slave中创建,该线程用于请求Master,Master会返回binlog的名称以及当前数据更新的位置、binlog文件位置的副本。

然后,将binlog保存在 「relay log(中继日志)」 中,中继日志也是记录数据更新的信息。

SQL线程也是在Slave中创建的,当Slave检测到中继日志有更新,就会将更新的内容同步到Slave数据库中,这样就保证了主从的数据的同步。

以上就是主从复制的过程,当然,主从复制的过程有不同的策略方式进行数据的同步,主要包含以下几种:

1、「同步策略」:Master会等待所有的Slave都回应后才会提交,这个主从的同步的性能会严重的影响。
2、「半同步策略」:Master至少会等待一个Slave回应后提交。
3、「异步策略」:Master不用等待Slave回应就可以提交。
4、「延迟策略」:Slave要落后于Master指定的时间。
对于不同的业务需求,有不同的策略方案,但是一般都会采用最终一致性,不会要求强一致性,毕竟强一致性会严重影响性能。

主从搭建

下面我们就来实操搭建主从,使用的是两台centos7并且安装的是Mysql 8来搭建主从,有一台centos 7然后直接克隆就行了。

(1)首先检查centos 7里面的Mysql安装包和依赖包:

rpm -qa |grep mysql

执行后,在我本机上的显示如下:
在这里插入图片描述
(2)接着可以删除上面的安装包和依赖包:

sudo yum remove mysql*

(3)继续检查一下是否存在Mariadb,若是存在直接删除Mariadb

// 检查是否存在Mariadb
rpm -qa |grep mariadb
// 删除Mariadb
sudo rpm -e --nodeps mariadb-libs-5.5.56-2.el7.x86_64

(4)然后,就是删除Mysql的配置文件,可以使用下面的命令查找Msqyl配置文件的路径:

sudo find / -name mysql

在我本机上的显示的Mysql配置文件的路径如下:
MySQL主从复制原理(原理+实操)_第2张图片
(5)然后,通过下面的命令,将他们逐一删除:

sudo rm -rf /usr/lib64/mysql
......

(6)接着就开始安装Mysql 8了,使用wget命令下载Mysql 8的repo源,并且执行安装:

wget https://repo.mysql.com//mysql80-community-release-el7-3.noarch.rpm
sudo yum -y install mysql80-community-release-el7-3.noarch.rpm

安装完后会在/etc/yum.repos.d/目录下生成下面的两个文件,说明安装成功了:

mysql-community.repo
mysql-community-source.repo

在这里插入图片描述
(7)安装完Mysql8后,接着来更新一下yum源,并且查看yum仓库中的Mysql:

// 更新yum源
yum clean all
yum makecache
// 查看yum仓库中的Mysql
yum list | grep mysql

(8)可以查看到仓库中存在mysql-community-server.x86_64,直接安装就行了:

sudo yum -y install mysql-community-server

(9)接着启动Mysql,并检查Mysql的状态:

// 启动Mysql
systemctl start  mysqld.service
// 检查Mysql的状态
systemctl status mysqld

确保查看Mysql的状态是active(running),表示正在运行,并且配置一下Mysql开机启动:

systemctl enable mysqld

MySQL主从复制原理(原理+实操)_第3张图片
(10)因为Mysql是新安装的,所以要修改一下初始密码,先查看一下初始密码:

grep "password" /var/log/mysqld.log

你可能找出来有多个,可能是你之前安装卸载后的文件没有删干净,这里你就直接看时间,时间对应你现在的时间,就是你的初始密码:
在这里插入图片描述
(11)然后使用初始密码,登陆数据库,并且修改密码:

mysql -uroot -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'LDCldc@123095;

(12)此时在创建一个可以用于给两一台centos连接的用户,默认的root用户只有本机才能连接:

// 创建连接用户
create user 'test'@'%' identified by 'LDCldc-2020';
// 并且把防火墙给关了,或者配置一下3306端口
systemctl stop firewalld.service;
// 设置防火墙开机自动关闭
systemctl disable firewalld.service;

(13)测试:到这里就Mysql的安装教程就就讲完了,可以测试一下,两台centos是否可以ping通:

ping 192.168.163.156

在这里插入图片描述
我这里的两台机是可以互通的,Master:192.168.163.156,Slave:192.168.163.155,并且Slave使用下面的命令可以登陆到Master的Mysql:

mysql -u[user] -p[密码] -h[远程主机ip]

确保了这两项测试成功后,就可以进行下面的主从搭建了。

(14)我这里使用的使用两台centos 7的vmware的ip分别是192.168.163.155(Slave)和192.168.163.156(Master)作为测试,首先在192.168.163.156(Master)中创建一个测试库test:

// 创建测试库
create database test default character set utf8mb4 collate utf8mb4_general_ci;
// 并且授权
grant all privileges on test.* to 'test'@'%';

(15)然后编辑Master中的my.cnf文件,此文件位于/etc/my.cnf,执行下面的sql,并添加下面的信息:

sudo vi /etc/my.cnf

==========以下是配置文件中的信息=============
# 配置编码为utf8
character_set_server=utf8mb4
init_connect='SET NAMES utf8mb4'

# 配置要给Slave同步的数据库
binlog-do-db=test
# 不用给Slave同步的数据库,一般是Mysql自带的数据库就不用给Slave同步了
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema
binlog-ignore-db=sys
# 自动清理30天前的log文件
expire_logs_days=30
# 启用二进制日志
log-bin=mysql-bin
# Master的id,这个要唯一,唯一是值,在主从中唯一
server-id=3

(16)配置完后重启Mysql服务,并查看Mysql的log_bin日志是否启动成功:

systemctl restart mysqld
# 查看log_bin日志是否启动成功
show variables like '%log_bin%';

MySQL主从复制原理(原理+实操)_第4张图片
(17)接着查看Master的状态:

show master status;

在这里插入图片描述
这两个数据File和Position要记住,后面配置Slave的时候要使用到这两个数据。

(18)最后登陆Master的数据库,并创建一个用户用于同步数据:

create user 'backup'@'%' IDENTIFIED BY 'LDCldc-2020';
grant file on *.* to 'backup'@'%';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* to 'backup'@'%';

到这里Master的配置就配置完了,后面就进行Slave的配置。

(19)在Slave中同样要创建test数据库,并且授权给test用户:

# 创建同步数据的test数据库
create database test default character set utf8mb4 collate utf8mb4_general_ci;
# 授权
grant all privileges on test.* to 'test'@'%';

(20)接着编辑Slave中my.cnf文件,同样是在/etc/my.cnf路径下,加入如下配置:

# 配置从服务器的ID,唯一的
server-id=4
#加上以下参数可以避免更新不及时,SLAVE 重启后导致的主从复制出错。
read_only = 1
master_info_repository=TABLE
relay_log_info_repository=TABLE

(21)并且重启Slave中的Mysql服务:

show slave status\G

MySQL主从复制原理(原理+实操)_第5张图片
当看到Slave_IO_Running和Slave_SQL_Running都是yes的时候,这表示主从配置成功。

「Slave_IO_Running也就是Slave中的IO线程用于请求Master,Slave_SQL_Running时sql线程将中继日志中更新日志同步到Slave数据库中。」

但是,有时候Slave_IO_Running会为no,而Slave_SQL_Running为yes,这时候需要检查一下原因,因为我自己初次搭建的时候,也是出现这个问题。

首先看重启一下Slave的MySQL服务:systemctl restart mysqld,然后执行:

stop slave;
start slave;

这样就能够使Slave_IO_Running和Slave_SQL_Running显示都是yes了。

(24)最后就是测试了,测试使用的是之前创建的test库,Master是用来写的,在Master的test库中随机创建一个表,你会发现Slave也会有这个表,插入数据也一样,都会被同步到Slave中。

主从面试

1、Mysql主从有什么优点?为什么要选择主从?

1、高性能方面:主从复制通过水平扩展的方式,解决了原来单点故障的问题,并且原来的并发都集中到了一台Mysql服务器中,现在将单点负载分散到了多台机器上,实现读写分离,不会因为写操作过长锁表而导致读服务不能进行的问题,提高了服务器的整体性能。

2、可靠性方面:主从在对外提供服务的时候,若是主库挂了,会有通过主从切换,选择其中的一台Slave作为Master;若是Slave挂了,还有其它的Slave提供读服务,提高了系统的可靠性和稳定性。

若是主从复制,达到了写性能的瓶颈,你是怎么解决的呢?

主从模式对于写少读多的场景确实非常大的优势,但是总会写操作达到瓶颈的时候,导致性能提不上去。

这时候可以在设计上进行解决采用分库分表的形式,对于业务数据比较大的数据库可以采用分表,使得数据表的存储的数据量达到一个合理的状态。

也可以采用分库,按照业务进行划分,这样对于单点的写,就会分成多点的写,性能方面也就会大大提高。

主从复制的过程有数据延迟怎么办?导致Slave被读取到的数据并不是最新数据。

主从复制有不同的复制策略,对于不同的场景的适应性也不同,对于数据的实时性要求很高,要求强一致性,可以采用同步复制策略,但是这样就会性能就会大打折扣。

若是主从复制采用异步复制,要求数据最终一致性,性能方面也会好很多。只能说,对于数据延迟的解决方案没有最好的方案,就看你的业务场景中哪种方案使比较适合的。

2、linux下实现MySQL主从复制(Master-Slave)

网站发展到一定程度应用服务器和数据库服务器分离,然后单台服务器满足不了生产需要就要做集群处理。特别是现在数据极其重要以及重视用户体验的年代,无论是在安全性,高可用性以及高并发等各个方面,我们都要做到万无一失。一直没时间整理,今天抽空整理了一下mysql主从复制从而实现读写分离,提升服务性能。

一般来说都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力 这样的方案来进行部署与实施的。复制(Replication)是从一台MySQL数据库服务器(主服务器master)复制数据到另一个服务器(从服务器slave)的一个进程。

如下图所示:
MySQL主从复制原理(原理+实操)_第6张图片
一、环境
主机:
master操作系统:centos 6.5
IP:192.168.1.190 (内网IP,实际情况为外网IP)
MySQL版本:5.1.73
从机:
slave操作系统:centos 6.5
IP:192.168.1.180 (内网IP,实际情况为外网IP)
MySQL版本:5.1.73

二、配置

配置主服务器(master)

1、编辑数据库配置文件my.cnf,一般在/etc/目录下。

#vi /etc/my.cnf
在[mysqld]的下面加入下面代码:

log-bin=mysql-bin
server-id=190
innodb_flush_log_at_trx_commit=1
sync_binlog=1
binlog-do-db=itstyle
binlog_ignore_db=mysql

server-id=190中的190可以任定义,只要是唯一的就行。
binlog-do-db=itstyle是表示只备份itstyle。
binlog_ignore_db=mysql表示忽略备份mysql。
不加binlog-do-db和binlog_ignore_db,那就表示备份全部数据库。

2、然后重启MySQL:

#service mysqld restart

3、登录MySQL服务器。

#mysql -uroot -p

在主服务器新建一个用户赋予“REPLICATION SLAVE”的权限。你不需要再赋予其它的权限。在下面的命,192.168.1.180是从服务器的IP,123456 是用户密码,这里可以自行修改。

mysql>CREATE USER 'mysqlcopy'@ '192.168.1.180' IDENTIFIED BY '123456';
mysql>GRANT REPLICATION SLAVE ON *.* TO 'user'@'192.168.1.180' IDENTIFIED BY '123456';

你可以查看用户是否创建成功。

mysql>use mysql
mysql>select * from user;

如果存在mysqlcopy用户,则说明成功。

配置从服务器(slave)

1、编辑配置文件my.cnf,在[mysqld]下面加入:

server-id=180

2可以自己定义,只要保证唯一的就行。

2、保存文件并重启mysqld。

#service mysqld restart

3、登录mysql服务器,执行以下命令。

mysql>CHANGE MASTER TO
MASTER_HOST='192.168.1.190',
MASTER_USER='mysqlcopy',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=98,
MASTER_CONNECT_RETRY=10;
MASTER_HOST:主服务器的IP。
MASTER_USER:配置主服务器时建立的用户名
MASTER_PASSWORD:用户密码
MASTER_PORT:主服务器mysql端口,如果未曾修改,默认即可。

注意 MASTER_LOG_FILE 文件名称一致,不然导致 Slave_IO_Running: NO

4、启动slave进程。

mysql>START SLAVE;
mysql>show slave status\G;

如果Slave_IO_Running、Slave_SQL_Running状态为Yes则表明设置成功。

显示如下:

*************************** 1. row ***************************
             Slave_IO_State: Waiting for master to send event
                Master_Host: 192.168.1.222
                Master_User: repl
                Master_Port: 3306
              Connect_Retry: 60
            Master_Log_File: log.000003
        Read_Master_Log_Pos: 98
            Relay_Log_File: mysqld-relay-bin.000002
              Relay_Log_Pos: 229
      Relay_Master_Log_File: log.000003
 
          Slave_IO_Running: Yes
          Slave_SQL_Running: Yes


            Replicate_Do_DB:
        Replicate_Ignore_DB:
         Replicate_Do_Table:
     Replicate_Ignore_Table:
    Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
                 Last_Errno: 0
                 Last_Error:
               Skip_Counter: 0
        Exec_Master_Log_Pos: 98
            Relay_Log_Space: 229
            Until_Condition: None
             Until_Log_File:
              Until_Log_Pos: 0
         Master_SSL_Allowed: No
         Master_SSL_CA_File:
         Master_SSL_CA_Path:
            Master_SSL_Cert:
          Master_SSL_Cipher:
             Master_SSL_Key:
      Seconds_Behind_Master: 0
1 row in set (0.00 sec)

显示红色那两行,说明配置成功。

5、查看mysql的日志,一般在/var/log/目录下的mysqld.log,如果启动成功,你应该会看到类似下面的日志。

[root@localhost ~]# vi /etc/my.cnf

091104 8:42:02 [Note] Slave I/O thread: connected to master ‘root@X.X.X.X:3306?, replication started in log ‘mysql-bin.000001? at position 98

现在主服务器和从服务器已经配置好了。另外你可能需要设置主服务器的数据库二进制日志的过期时间,可以在配置文件中使用参数expire_logs_days来设定。

可能出现问题
一、 无法连接主服务器
1.查看配置文件:
skip-networking #注释掉 因为它是屏蔽掉一切TCP/IP连接
bind-address = 127.0.0.1 #它和上一个选项是异曲同工,要想远程连接,也得注释掉

2.如果以上工作都做过还是出现:
ERROR 2003 (HY000): Can’t connect to MySQL server on ‘...’ (113),那就得考虑防火墙的问题了,关掉防火墙/etc/rc.d/init.d/iptables stop

二、Slave_IO_Running: No
其实就是无法连接主服务器导致的,当然还有其他问题。












参考链接 :

MySQL主从复制原理(原理+实操) : https://mp.weixin.qq.com/s/3UpNwEmCYcn0yvlPRklsXw

linux下实现MySQL主从复制(Master-Slave) : https://mp.weixin.qq.com/s/_mATubcJFOvAXkPzDLpnvw

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