MySQL数据库主从架构

在这里插入图片描述

为什么会用到MySQL主从架构?

1.做数据的热备,将从库作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
2.满足业务需求,当业务量越来越大,O/I频率越来越高,单个主机已经无法满足需求,增添架构,可以分担业务量,提升O/I性能,也就是所谓的负载均衡。
3.为MySQL其他架构做基础,例如:读写分离,高可用。

什么是MySQL主从复制(REPLICATION)?

通过字面上来看,最起码要有两台数据库,并且他们的关系是主与从。MySQL主从复制就是将数据库群中一台或多台服务器作为主(master)数据库,其他数据库作为从(slave)数据库,然后指向主库,实时同步主库中的数据;当主库数据发生变化时,会将变化的数据实时同步到一个或多个从库。

MySQL主从复制过程

其中涉及到了三个线程和两个日志:
Binary log(二进制日志)和Binary log Jump Thread(二进制日志线程)属于主数据库。
I/OThread(输入/输出线程),Relay Log(中继日志)和SQL Thread(SQL线程)属于从数据库。

对于日志就不用多说了,不管是二进制日志还是中继日志,其中存放的都是SQL语句。

线程解释:
Binary log dump 线程
当从节点连接主节点后,主节点会创建一个log dump线程,用于发送binlog日志中的内容。

I/O线程
当从节点执行"start slave"命令后,从节点会创建一个I/O线程用来连接主节点,请求主库更新的binlog日志。I/O线程接收到主节点log dump线程发来的更新数据之后,保存到本地的relay log日志。

SQL线程
SQL线程读取relay log日志中的内容,然后解析成具体的SQL语句并执行,最终完成数据同步。

在这里插入图片描述
主从复制过程:
1)主节点数据更新,随后将具体的更新语句写到binlog日志中。

2)从节点开启主从复制功能,创建一个I/O线程,连接主节点。

3)主节点接收到从节点的连接后,创建一个binary log dump线程,把binlog日志中更新的内容发送到从节点。

4)从节点的I/O线程读取主节点发送的binlog日志,并写入到relay log中。

5)从库创建SQL线程,读取relay log日志中的内容,并解析执行,完成数据同步。

以上描述是一主一从架构,若是其他架构,其原理也是一样的,只不过细节上稍微有一点不一样。例如:一主多从架构,在主从复制时,主节点会分别为每个从节点创建一个binary log dump线程传递更新数据,而从节点使用各自的I/O线程和SQL线程。

二进制日志格式

MySQL的三种复制方式:
基于SQL语句复制(statement-based replication,简称SBR)
基于行的复制(row-based replication,简称RBR)
混合模式复制(mixed-based replication,简称MBR)

根据不同的方式,binlog日志的格式也有三种,分别是:STATEMENT(基于SQL语句复制),ROW(基于行的复制),MIXED (混合模式复制)。

STATEMENT模式(SBR)

会将数据修改的SQL语句写到binlog日志中,无需记录每行数据变化,减少了日志量,但有些数据无法保存,不能保证数据的一致性。

ROW模式(RBR)

此模式为默认。

仅记录数据被修改,修改成什么样子,不记录SQL语句信息,很大程度上保证了数据的一致性,但会产生大量的日志。

MIXED模式(MBR)

结合STATEMENT模式和ROW模式使用,优先使用STATEMENT模式保存binlog,对于STATEMENT模式无法保存的数据,则使用ROW模式进行保存。对于STATEMENT模式是否能够保存数据,由MySQL自行判断。

MySQL主从复制模式

全同步模式
主库执行完一个事务后,所有从库也执行该事务,当所有从库都执行完该事务后才返回给客户端。

优点:确保数据的一致性
缺点:性能影响严重

异步复制

此模式为默认。

主库执行完一个事务后,立即将更新数据发送给从库,并不关心从库是否接收。

优点:减少部分资源消耗
缺点:无法确认从库是否复制成功

半同步模式
相当于异步复制的改良版,主库执行完事务后,至少一个从库接收并写入到relay log中才返回给客户端。

优点:确保从库复制成功
缺点:这个过程需要花费一部分时间

MySQL架构方案

一主一从
在这里插入图片描述
提升负载均衡

一主多从
在这里插入图片描述
提升负载均衡,可用于高可用和读写分离,但主节点I/O压力较大。

多主一从
在这里插入图片描述
适用于写操作较为频繁的环境。

互为主从
在这里插入图片描述
也叫做双主互备,用于读写操作都较为频繁的环境。

注:有人说这个架构可以提供负载均衡,我个人认为对的,但是每当有一个库数据更新,另一个库都需要消耗一部分资源来进行同步数据,架构还不如使用一主一从。

联机复制
在这里插入图片描述
将一台从库作为中继,减轻主库的I/O压力。

更改二进制日志格式

对于二进制日志的保存操作,默认的ROW格式并不是一个很好的选择,其会产生大量的日志数据,对后续的主从复制效率不高。

查看binlog格式

mysql> show variables like "binlog_format";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+

其实不管是主从架构,还是单纯的保存binlog日志,ROW格式都不是最好的选择,建议使用MIXED格式,其结合STATEMENT模式和ROW模式保存数据,即能减少日志的大小,又能确保数据的完整。

直接编辑/etc/my.cnf配置文件,在其中指定binlog日志格式即可。

binlog-format=MIXED

随后重启数据库,刷新配置。

/etc/init.d/mysql.server restart 

再次进入到数据库中查看binlog日志格式

mysql> show variables like "binlog_format";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | MIXED |
+---------------+-------+

已成功更改为MIXED模式。

MySQL主从复制部署

以一主一从为例,列举了MySQL架构的搭建过程。

环境准备

系统版本/MySQL版本 主机名 IP地址 角色 准备
CentOS7.7/MySQL8.0.13 linux.node1 192.168.1.123 master 关闭防火墙,selinux
CentOS7.7/MySQL8.0.13 linux.node2 192.168.1.123 slave 关闭防火墙,selinux

一主一从架构部署

1)搭建时间同步服务

对于数据的实时同步,若两台服务器的时间都对不上,又谈何而来的实时同步呢?

主节点安装NTP服务

yum install -y ntp

修改ntp服务的配置文件,路径位于 /etc/ntp.conf ,并添加以下两项

server 127.127.1.0  #权威NTP不可用时,本机时间作为时间服务
fudge 127.127.1.0 stratum 8 #NTP服务的阶级层数,同步上层服务器的stratum 大小不能超过或等于16

开启服务

systemctl start ntpd

查看端口

netstat -anpu | grep ntpd
udp        0      0 192.168.122.1:123       0.0.0.0:*                           2726/ntpd           
udp        0      0 192.168.1.123:123       0.0.0.0:*                           2726/ntpd           
udp        0      0 127.0.0.1:123           0.0.0.0:*                           2726/ntpd           
udp        0      0 0.0.0.0:123             0.0.0.0:*                           2726/ntpd           
udp6       0      0 fe80::8c62:89:ad82::123 :::*                                2726/ntpd           
udp6       0      0 ::1:123                 :::*                                2726/ntpd           
udp6       0      0 :::123                  :::*                                2726/ntpd           

从节点安装ntp客户端

yum install -y ntpdate

与主节点同步时间

ntpdate 192.168.1.123
19 Jun 16:31:27 ntpdate[61266]: adjust time server 192.168.1.123 offset 0.459178 sec

显示将时间偏移了0.459178秒,时间同步成功。

注:以下为主节点配置

2)创建测试数据

mysql> create database replication;
mysql> use replication;
mysql> create table test(id int,name varchar(233));
mysql> insert into test values(1,'一主一从');

3)创建主从复制授权用户

mysql> create user 'slave'@'192.168.1.%' identified by '123456'; 
mysql> grant replication slave on *.* to 'slave'@'192.168.1.%';
mysql> flush privileges;

4)修改my.cnf文件

以下为添加配置项

server-id=1
binlog-format=MIXED
log-bin=/data/mysql/log/mysql-bin-master
binlog-do-db=replication
#binlog-ignore-db=mysql

server-id: mysql的同步的数据中是包含server-id的,用于标识该语句最初是从哪个server写入,不同节点的server-id不能相同。
binlog-format:binlog日志格式
log-bin:binlog日志存放路径
binlog-do-db:指定binlog日志保存哪个库的数据记录,不添加为全库。
binlog-ignore-db:指定binlog日志不保存哪个库的数据记录,不添加为全部不保存。(若有binlog-do-db配置项,则只保存其指定的库)

重启数据库,刷新配置

/etc/init.d/mysql.server restart 

5)查看生成的二进制日志

ls /data/mysql/log/
mysql-bin-master.000001  mysql-bin-master.index  mysqld.log

数据库中查看

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-master.000001
         Position: 155
     Binlog_Do_DB: replication
 Binlog_Ignore_DB: mysql
Executed_Gtid_Set: 

6)将主库的数据传入从库

mysqldump -uroot replication > db.sql
scp db.sql root@192.168.1.124:~
The authenticity of host '192.168.1.124 (192.168.1.124)' can't be established.
ECDSA key fingerprint is SHA256:dt6xhgOGH0g33XrYjk1qPbtD4C2hg62DlqfRMoUSK88.
ECDSA key fingerprint is MD5:9b:ef:79:5b:01:9e:63:0d:75:a7:c7:3e:62:a7:6a:04.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.124' (ECDSA) to the list of known hosts.
root@192.168.1.124's password: 
db.sql                                     100% 1817     2.3MB/s   00:00    

注:以下为从节点配置

7)从库将SQL脚本导入库中

mysql -uroot -e "create database replication;"
mysql replication < db.sql 

查看数据是否导入成功

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| replication        |
| sys                |
+--------------------+

8)修改my.cnf文件
在原有基础上添加以下配置项

server-id=2
relay-log=/data/mysql/log/relay-log-bin
relay-log-index=/data/mysql/log/slave-relay-bin.index
#replicate_do_db=replication

server-id:服务器ID号
relay-log:relay-log日志存放路径
relay-log-index:relay-log日志的索引文件存放路径
replicate_do_db:指定从库复制的数据库

重启服务,刷新配置

/etc/init.d/mysql.server restart 

9)测试授权用户是否可以登录主库

mysql -uslave -h192.168.1.123 -p123456

登录进去后,查看其中的数据库

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
+--------------------+

因为只有主从复制权限,其他权限没有开放,所以是看不到其他库的,但不影响查看数据库的命令执行。

10)从库使用授权用户连接主库

这里的授权用户是由主库创建的,本案例中的为slave。

数据库默认是开启主从复制的,先关闭

mysql> stop slave;

连接主库,具体参数根据实际情况指定

mysql> change master to master_host='192.168.1.123',master_user='slave',master_password='123456',master_log_file='mysql-bin-master.000001',master_log_pos=155;

以下为此案例中主库的binlog日志文件,用于理解命令

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-master.000001
         Position: 155
     Binlog_Do_DB: replication
 Binlog_Ignore_DB: mysql
Executed_Gtid_Set: 

解读:
master_host:主库IP地址
master_user:主库授权用户
master_password:主库授权用户密码
master_log_file:主库binlog日志文件名称
master_log_pos:主库binlog日志文件位置

开启主从复制功能

mysql> start slave;

11)分别在主库和从库中查看主从复制状态

从库中查看

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.123
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-master.000001
          Read_Master_Log_Pos: 155
               Relay_Log_File: relay-log-bin.000002
                Relay_Log_Pos: 329
        Relay_Master_Log_File: mysql-bin-master.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: replication
          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: 155
              Relay_Log_Space: 535
              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
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 1b3423c4-b047-11ea-bfaa-000c29bbe2d8
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
       Master_public_key_path: 
        Get_master_public_key: 0

其中 Slave_IO_Running和Slave_SQL_Running线程为YES,表示主库连接成功,也就是说主从复制搭建成功了。有一个为Connecting,都表示主从复制没有搭建成功。

主库中查看

mysql> show processlist\G
...
*************************** 3. row ***************************
     Id: 18
   User: slave
   Host: 192.168.1.124:43856
     db: NULL
Command: Binlog Dump
   Time: 716
  State: Master has sent all binlog to slave; waiting for more updates
   Info: NULL

可以看到binlog dump线程已经建立,连接的主机为192.168.1.124。

12)验证主从复制功能
主库现有数据

mysql> select * from replication.test;
+------+--------------+
| id   | name         |
+------+--------------+
|    1 | 一主一从     |
+------+--------------+

从库现有数据

mysql> select * from replication.test;
+------+--------------+
| id   | name         |
+------+--------------+
|    1 | 一主一从     |
+------+--------------+

在主库中插入数据

mysql> insert into replication.test values(2,'测试');

在从库中查看数据是否同步成功

mysql> select * from replication.test;
+------+--------------+
| id   | name         |
+------+--------------+
|    1 | 一主一从     |
|    2 | 测试         |
+------+--------------+

若是主从状态正常,但数据没有同步成功,那一定概率就是主库的binlog日志位置变了,重新查看主库的binlog日志位置,再次连接主库即可。

或者说删除binlog日志(reset master),重新创建并连接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章