MySQL数据库集群——MySQL的异步复制(基于position的主从复制和基于gtid的主从复制),半同步复制,组复制

本文详细介绍了MySQL数据库的主从复制原理与应用,包括异步复制、基于position和GTID的主从复制,以及半同步复制。通过主从复制实现读写分离、数据备份和高可用性。此外,还探讨了MySQL的组复制,提供了一种高一致性和容错性的解决方案。文章通过实验环境展示了如何配置和管理这些复制模式。

以下所有的实操都是在redhat7.3上操作


MySQL (关系型数据库管理系统)的基础知识

1.什么是数据库?
数据库,简而言之可视为电子化的文件柜——存储电子文件的处所,用户可以对文件中的数据进行新增、查询、更新、删除等操作
所谓“数据库”是以一定方式储存在一起、能与多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合
2.什么是数据库管理系统?

数据库管理系统(英语:Database Management System,简称DBMS)是为管理数据库而设计的电脑软件系统

一般具有存储、截取、安全保障、备份等基础功能。
数据库管理系统可以依据它所支持的数据库模型来作分类,例如关系式、XML;
或依据所支持的计算机类型来作分类,例如服务器群集、移动电话;
或依据所用查询语言来作分类,例如SQL、XQuery;
或依据性能冲量重点来作分类,例如最大规模、最高运行速度;
亦或其他的分类方式。不论使用哪种分类方式,一些DBMS能够跨类别,例如,同时支持多种查询语言。
3.数据库的分类

<1>关系数据库

MySQL
MariaDB(MySQL的代替品,英文维基百科从MySQL转向MariaDB)
Percona Server(MySQL的代替品·)
PostgreSQL
Microsoft Access
Microsoft SQL Server
Google Fusion Tables
FileMaker
Oracle数据库
Sybase
dBASE
Clipper
FoxPro
foshub

几乎所有的数据库管理系统都配备了一个开放式数据库连接(ODBC)驱动程序,令各个数据库之间得以互相集成。
<2>非关系型数据库(NoSQL)

BigTable(Google)
Cassandra
MongoDB
CouchDB
键值(key-value)数据库
Apache Cassandra(为Facebook所使用):高度可扩展
Dynamo
LevelDB(Google)
4.数据库模型
对象模型
层次模型(轻量级数据访问协议)
网状模型(大型数据储存)
关系模型
面向对象模型
半结构化模型
平面模型(表格模型,一般在形式上是一个二维数组。如表格模型数据Excel)
5.数据库架构

数据库的架构可以大致区分为三个概括层次:内层、概念层和外层。

内层:最接近实际存储体,亦即有关数据的实际存储方式。
外层:最接近用户,即有关个别用户观看数据的方式。
概念层:介于两者之间的间接层。
6.数据库索引
数据索引的观念由来已久,像是一本书前面几页都有目录,目录也算是索引的一种,只是它的分类较广,例如车牌、身份证字号、条码等,都是一个索引的号码,当我们看到号码时,可以从号码中看出其中的端倪,若是要找的人、车或物品,也只要提供相关的号码,即可迅速查到正确的人事物。
另外,索引跟字段有着相应的关系,索引即是由字段而来,其中字段有所谓的关键字段(Key Field),该字段具有唯一性,即其值不可重复,且不可为"空值(null)"。例如:在合并数据时,索引便是扮演欲附加字段数据之指向性用途的角色。故此索引为不可重复性且不可为空。
数据库操作:事务
7.数据库事务

事务(transaction)是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。
事务的ACID特性:
事务的ACID特性:
原子性(atomicity):一个事务是一个不可分割的最小工作单位,事务中的所有操作要么都做,要么都不做。
一致性(consistency):事务前后数据的完整性必须保持一致.事务必须是使数据库从一个一致性状态变到另一个一致性状态,一致性与原子性是密切相关的。
隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。有四种隔离级别
持久性(durability):指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

隔离性的四种级别

在这里插入图片描述

8.什么是mysql?

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品
MySQL 是最流行的关系型数据库管理系统之一
在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一
MySQL是一种关系数据库管理系统,关系数据库将数据保存在不同的表中
而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性
MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言
MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点
一般中小型网站的开发都选择 MySQL 作为网站数据库
由于其社区版的性能卓越,搭配 PHP 和 Apache 可组成良好的开发环境

关于mysql数据库集群的英文文档

一、MySQL 主从复制(异步复制)概念

MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,数据的更新可以在远程连接上进行,从节点可以复制主数据库中的所有数据库或者特定的数据库,或者特定的表。

二、MySQL 主从复制主要用途

1. 读写分离
在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
2. 数据实时备份,当系统中某个节点发生故障时,可以方便的故障切换
3. 高可用HA
4. 架构扩展
随着系统中业务访问量的增大,如果是单机部署数据库,就会导致I/O访问频率过高。有了主从复制,增加多个数据存储节点,将负载分布在多个从节点上,降低单机磁盘I/O访问的频率,提高单个机器的I/O性能

三、MySQL 主从复制原理

MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread, SQL thread)运行在从节点,如下图所示:
在这里插入图片描述
更细致的解读mysql主从复制原理
在这里插入图片描述

主节点 binary log dump 线程

当从节点连接主节点时,主节点会创建一个log dump 线程,用于发送bin-log的内容。在读取bin-log中的操作时,此线程会对主节点上的bin-log加锁,当读取完成,甚至在发动给从节点之前,锁会被释放。

从节点I/O线程

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

从节点SQL线程

SQL线程负责读取relay log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。

对于每一个主从连接,都需要三个进程来完成。当主节点有多个从节点时,主节点会为每一个当前连接的从节点建一个binary log dump 进程,而每个从节点都有自己的I/O进程,SQL进程。从节点用两个线程将从主库拉取更新和执行分成独立的任务,这样在执行同步数据任务的时候,不会降低读操作的性能。比如,如果从节点没有运行,此时I/O进程可以很快从主节点获取更新,尽管SQL进程还没有执行。如果在SQL进程执行之前从节点服务停止,至少I/O进程已经从主节点拉取到了最新的变更并且保存在本地relay日志中,当服务再次起来之后,就可以完成数据的同步。

要实施复制,首先必须打开Master 端的binary log(bin-log)功能,否则无法实现。

因为整个复制过程实际上就是Slave 从Master 端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。如下图所示:
在这里插入图片描述
复制的基本过程如下:

  1. 从节点上的I/O 进程连接主节点,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
  2. 主节点接收到来自从节点的I/O请求后,通过负责复制的I/O进程根据请求信息读取指定日志指定位置之后的日志信息,返回给从节点。返回信息中除了日志所包含的信息之外,还包括本次返回的信息的bin-log file 的以及bin-log position;从节点的I/O进程接收到内容后,将接收到的日志内容更新到本机的relay log中,并将读取到的binary log文件名和位置保存到master-info 文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log 的哪个位置开始往后的日志内容,请发给我”;
  3. Slave 的 SQL线程检测到relay-log 中新增加了内容后,会将relay-log的内容解析成在祝节点上实际执行过的操作,并在本数据库中执行。

在这里插入图片描述

四、实现Mysql主从复制(基于position的主从复制)

异步复制:当数据复制一半,master卡死,那么数据就会丢失;master和slave不是同步的;
单向复制,只能slave复制master的,即slave对master库只读

server1172.25.70.1master
server2172.25.70.2slave
在master(server1)配置:

mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar安装包下载

[root@server1 ~]# cd mysql_inst/
[root@server1 mysql_inst]# ls
mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
[root@server1 mysql_inst]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar  #解压mysql安装包 
[root@server1 mysql_inst]# ls
[root@server1 mysql_inst]# rpm -qa |grep mariadb   #查看是否存在mariadb
mariadb-libs-5.5.52-1.el7.x86_64
[root@server1 mysql_inst]# yum install -y mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm
[root@server1 mysql_inst]# rm -fr mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar mysql-community-devel-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-compat-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-devel-5.7.24-1.el7.x86_64.rpm mysql-community-minimal-debuginfo-5.7.24-1.el7.x86_64.rpm mysql-community-server-minimal-5.7.24-1.el7.x86_64.rpm mysql-community-test-5.7.24-1.el7.x86_64.rpm

在这里插入图片描述
在这里插入图片描述

[root@server1 mysql_inst]# scp * server2:   #将其安装包发给server2
[root@server1 mysql_inst]# scp * server3:
[root@server1 mysql_inst]# vim /etc/my.cnf
log-bin=mysql-bin  #启用二进制功能,主从复制基础
server-id=1    #id唯一,id不一样,刚好避免了死循环复制,看到id不一样,直接丢弃不一样的事务

在这里插入图片描述

[root@server1 mysql_inst]# cd /var/lib/mysql
[root@server1 mysql]# ls  #mysql下无任何文件
[root@server1 mysql]# systemctl start mysqld  #启动mysql服务;
[root@server1 mysql]# ls

在这里插入图片描述

[root@server1 ~]# grep password /var/log/mysqld.log #获得初始密码

在这里插入图片描述

[root@server1 ~]# mysql_secure_installation  #重新设置root密码;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

[root@server1 ~]# mysql -uroot -pWang+123   #登录数据库
mysql> CREATE USER 'repl'@'172.25.70.%' IDENTIFIED BY 'Wang+123'; #创建用户;
mysql> GRANT REPLICATION SLAVE ON *.*  TO 'repl'@'172.25.70.%';  #  为服务器创建一个连接账户并授予权限,*.*表示所有权限;172.25.70.%表示这个网段的所有用户都有这个权限
mysql> SHOW DATABASES;

在这里插入图片描述

mysql> USE mysql
mysql> select * from  tables_priv;
mysql> show master status;
当前正在使用的二进制日志文件

在这里插入图片描述

测试:在server3上,在server2上也可以;
[root@server3 ~]# mysql -h 172.25.70.1 -urepl -pWang+123 
mysql> show databases;#远程登录,但是不能查看数据库; 测试成功

在这里插入图片描述

mysql> quit
在slave(server2)配置:
[root@server2 ~]mkdir mysql_inst
[root@server2 mysql_inst]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar  #解压mysql安装包 
[root@server2 mysql_inst]# yum install -y mysql-community-client-5.7.24-1.el7.x86_64.rpm mysql-community-common-5.7.24-1.el7.x86_64.rpm mysql-community-libs-5.7.24-1.el7.x86_64.rpm mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm mysql-community-server-5.7.24-1.el7.x86_64.rpm

在这里插入图片描述

[root@server2 mysql_inst]# vim /etc/my.cnf;
server-id=2

在这里插入图片描述

[root@server2 mysql_inst]# systemctl start mysqld  #重启服务
[root@server2 mysql_inst]# cd /var/lib/mysql
[root@server2 mysql]# ls
[root@server2 mysql]# grep password /var/log/mysqld.log
[root@server2 mysql]# mysql_secure_installation
[root@server2 ~]# mysql -uroot -pWang+123   #登录数据库
mysql> show databases;

mysql> CHANGE MASTER TO
    -> MASTER_HOST='172.25.70.1',
    -> MASTER_USER='repl',
    -> MASTER_PASSWORD='Wang+123',
    -> MASTER_LOG_FILE='mysql-bin.000002',
    -> MASTER_LOG_POS=1834;
mysql> start slave; #表示同时启动i/o线程和SQL线程;
I/O线程从主库读取mysql-bin .log并存储到server-relay-bin. log中继日志文件中;
SQL读取server-relay-bin. log中继日志,解析后,在从库重放;
mysql> show slave status\G;

在这里插入图片描述

这步不操作,只是为了说明stop slave的含义;
*****************************************
mysql> stop slave  #完成停止I/O线程和SQL线程;
******************************************
在master(server1)上创建数据库:
mysql> create database westos;
mysql> use westos
mysql> create table usertb(
    -> username varchar(10) not null,
    -> password varchar(15) not null);  #创建属性;
mysql> desc usertb; #查看表的属性

在这里插入图片描述

mysql> insert into usertb values('user1','123');      #插入用户;
mysql> select * from usertb;      #查看表格;

在这里插入图片描述

[root@server1 ~]# mysqlbinlog mysql-bin.000003  打开二进制文件,不能用cat打开,否则是乱码;
在slave(server2)查看是否同步:
[root@server2 ~]# mysql -uroot -pWang+123
mysql> show databases;

在这里插入图片描述

mysql> use westos;
mysql> show tables;

在这里插入图片描述

mysql> select * from usertb; #同步成功,主从复制成功;

在这里插入图片描述


五、实现mysql的异步复制(基于gtid的主从复制)

相比于传统的主从复制优点:不需要知道复制哪个文件,也不需要知道从哪个号开始复制,但是异步复制的效率高,master节点不会等待slave节点
基于gtid的主从复制不容易因为master一个事件的中断而造成数据丢失而不能复制
基于position的主从复制容易因为master一个事件的中断而造成数据丢失而不能复制

1、实现mysql的异步复制(基于gtid的主从复制)(以一个事件为单位进行复制)

从事务1开始复制;,如果主库down掉,从库只会将其垃圾数据删除,之前从库复制的事务是保存不变,一旦主库正常,从库会继续复制;

1.简述GTID
GTID分成两部分,一部分是服务的UUID, UUID保存在mysql数据目录的auto.cnf文件中,这是一个非常重要的文件,不能删除,这一部分是不会变的。
另外一部分就是事务ID了,随着事务的增加,值一次递增。在整个复制架构中GTID 是不变化的,即使在多个连环主从中也不会变。
2.工作原理

在这里插入图片描述

工作过程
1.master更新数据时,会在事务前产生GTID,一同记录到binlog(二进制日志)中。
2.每当有slave连接到master的时候,master都会创建一个dump线程然后发送binlog(二进制日志)内容到slave。
3.slave端的IO线程将变更的binlog,写入到本地的 relay log 中。
4.slave端的SQL线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。
5.如果有记录,说明该GTID的事务已经执行,slave会忽略。
6.如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
7.在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
3.特点:
1.一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次
2.GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置
3.减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机
4.总结
基于GTID的主从复制与传统的主从复制最大的区别在于:传统的是根据position号来确定从哪开始复制,而GTID的会自动读取gtid_next变量,即告诉Slave,下一个要执行的GTID值

实验环境

这个是在基于position的主从复制的基础上继续做的
因此这里的实验环境就不再赘述
在这里插入图片描述
在这里插入图片描述

在server1(master)上
1.开启gtid
[root@server1 mysql]# vim /etc/my.cnf
log-bin=mysql-bin
server-id=1事务的安全
gtid_mode=ON  #启动gtid模式
enforce-gtid-consistency=ON #强制gtid一直性,用于保证启动gtid后

在这里插入图片描述

2.重启数据库
[root@server1 mysql]# systemctl restart mysqld
3.登录数据库

当重启数据库的时候,发现日志名称和日志号会发生变更

[root@server1 mysql]# mysql -uroot -pWang+123
mysql> show master status;查看master的状态;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 (日志名称)|      154 (日志号)|              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
mysql> exit

在这里插入图片描述

#查看GTID
[root@server1 ~]#  mysql -uroot -phym19970818HYM#
mysql> show databases;
mysql> use mysql;
mysql> show tables;                   #查看到记录GTID的表
mysql> select * from gtid_executed;   #查看GTID信息,当前表中没有信息
mysql> exit

在这里插入图片描述
在这里插入图片描述

[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# ls
[root@server1 mysql]# cat auto.cnf查看改节点的uuid

在这里插入图片描述

[root@server1 mysql]# mysqlbinlog mysql-bin.000001  #打开二进制文件,不能用cat打开,否则是乱码;

在这里插入图片描述

如果是基于position的主从复制:将一个事件拆开来复制,如果一个事件进行的过程中出现问题,那么复制也会出现问题
如果是基于gtid的主从复制:一个以事件为单位进行复制,如果一个事件进行的过程中出现问题,那么复制也不会出现问题

#查看改节点的UUID


[root@server1 mysql]# cat auto.cnf 
[auto]
server-uuid=8763e372-e140-11e9-bf5b-525400b8da0f
在slave(server2)上:
[root@server2 ~]# cd  /var/lib/mysql
[root@server2 mysql]# ls
[root@server2 ~]# vim /etc/my.cnf
server-id=2
gtid_mode=ON  
enforce-gtid-consistency=ON

在这里插入图片描述

[root@server2 mysql]# systemctl restart mysqld
[root@server2 mysql]# mysql -uroot -pWang+123
mysql> stop slave;
mysql> change master to master_host='172.25.70.1',master_user='repl',master_password='Wang+123',MASTER_AUTO_POSITION=1;   # 改变slave服务器用于连接master服务器的参数,此处把MASTER值设为动态
mysql> start slave;
mysql> show slave status\G;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在server1的数据库上面开始写数据
mysql> show databases;
mysql> use westos;
mysql> insert into usertb values ('user2','123');
mysql> insert into usertb values ('user3','123');

在这里插入图片描述

在server2上面查看gtid的信息
mysql> show slave status\G;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在server1上面查看gtid的信息
mysql> use mysql
mysql> select * from gtid_executed;

在这里插入图片描述

在server2上面查看复制过来的数据
mysql> use mysql
mysql> select * from mysql.gtid_executed;
发现slave完成了master的所有事件

在这里插入图片描述
在这里插入图片描述

mysql主从复制存在的问题:
1.主库宕机后,数据可能丢失
2.从库只有一个sql Thread,主库写压力大,复制很可能延时
解决方法:
1.半同步复制----解决数据丢失的问题
2.并行复制----解决从库复制延迟的问题

六、实现MySQL的半同步复制(基于gitd的半同步复制)

1.mysql半同步复制的基础知识

半同步复制:一主多从模式下,有一个从节点返回成功,即成功,不必等待多个节点全部返回

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。

在这里插入图片描述
主从同步可以同步多个数据库,也可以设置为一个数据库同步,如果设置一个数据库,在从服务器上其他数据可以写操作半同步复制模式在主服务器和从服务器同时启用,否则主服务器默认使用异步复制模式

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

为了解决上述出现的问题,MySQL 5.5 引入了一种半同步复制模式。该模式可以确保从库接收完主库发送的binlog日志文件并写入到自己的中继日志relay log里,然后会给主库一个反馈,告诉主库已经接收完毕,这时主库才返回结果给客户端告知操作完成。当出现从库响应超时情况时,主库会暂时切换到异步复制模式,直到下一次同步没有超时转为半同步复制为止。(master的dump线程除了发送binlog数据到slave,还承担了接收slave的ack工作。如果出现异常,没有收到ack,那么将自动降为普通的异步复制,直到异常修复)

实验环境

此实验是基于异步复制的基础上做的,因此不再赘述

在这里插入图片描述
在这里插入图片描述

1、在server1(master节点)上安装半同步复制的插件
[root@server1 mysql]# mysql -uroot -pWang+123
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';#下载插件,安装半同步模块

在这里插入图片描述

2、在server2(slave节点)上安装半同步复制的插件
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';#下载插件;

在这里插入图片描述

3、在server1上查看插件
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
    ->  FROM INFORMATION_SCHEMA.PLUGINS
    -> WHERE PLUGIN_NAME LIKE '%semi%';  #查看插件是否加载成功;

在这里插入图片描述

4、在server2查看插件

在这里插入图片描述

5、在server1上激活插件
mysql> show global variables like '%semi%'; 
mysql>  SET GLOBAL rpl_semi_sync_master_enabled =1;#激活半同步复制,这是临时设置,永久设置需要在编辑文件/etc/my.cnf中写入
mysql> show variables like '%rpl%';

在这里插入图片描述

mysql> show status like '%rpl%';  #查看status状态是否激活为半同步复制状态,可以用这些参数进行监控

在这里插入图片描述

mysql>  show status like 'Rpl_semi_sync_master_status';  # 查看半同步是否在运行

在这里插入图片描述

6、在server2上激活插件
mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;  #激活半同步复制
mysql> STOP SLAVE IO_THREAD; #重启slave上的I/O线程,重启后,slave会在master上注册为半同步复制的slave角色,否则还是异步复制
mysql> START SLAVE IO_THREAD;#开启
mysql> show variables like '%rpl%';
mysql> show slave status\G;

·从库重启io进程,激活插件之后必须要重启io进程,否则不会生效,如果重启不了的话就说明两端的数据不同步

7、server1:查看主库的变量的值,可以查看到延迟时间(10000指10000毫秒,也就是10秒)
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';查看变量的值
mysql> show status like '%rpl%';查看变量的状态

在这里插入图片描述
在这里插入图片描述

8、在server2先关闭io进程:
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
mysql> STOP SLAVE IO_THREAD;关闭从库进行测试

在这里插入图片描述

9、server1:
mysql> use westos
mysql> insert into usertb values ('user4','123');
等待10s,没有接收到slave的ack请求,自动转换为异步复制,需要等待一个节点完成所有的复制
mysql> insert into usertb values ('user5','123');发现特别快,已经变成异步了
mysql> show status like '%rpl%';发现半同步已经关闭OFF

在这里插入图片描述
有10秒的延迟,这是因为从库的io进程关闭了,不能及时的写入数据;主库等待10秒之后从库还没有起来,主库不再等待直接写入
等待完毕,10秒后直接写入
再次插入数据,主库直接写入,没有延迟
在这里插入图片描述
这是因为:半同步复制再一次失败后会自动切换成异步复制,从库进程起来之后会将没有做的事情再做一遍

10、server2:
mysql> START SLAVE IO_THREAD;开启
mysql> show processlist;
mysql> use westos
mysql> select * from usertb;发现所有的数据都过来了(基于gtid),接着上一次的事情做

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

关闭server2上面的slave,然后在server1上面插入数据
sever1(master)等待10s发现server2(slave)没有发送ACK消息,自动变为异步同步,
然后在server2上把slave上面开启,会把之前的数据读过来

也就是说只要从库的io进程恢复工作就会立即同步没有同步的数据
半同步复制失败后会自动切换成异步复制,从库进程起来之后会检测主从库数据是否同步;若不同步,将会采用异步复制的方式同步数据
将插件安装在数据库中是临时的,退出重新登陆会失效,永久的可以将配置写在配置文件中


七、基于gtid实现并行复制

为什么会出现并行复制呢?

因为在5.7的mysql生产环境中,slave端进行复制时,IO线程和SQL线程都是单线程,而master端
是多线程,多新城肯定比单线程快的多,这就出现了复制延迟的问题,我们用并行复制就可以解决
这个问题,并行复制的目的就是要让slave尽可能的多线程跑起来,当然基于库级别的多线程也是
一种方式(不同库的事务,没有锁冲突)
在server2(slave)上
[root@server2 ~]# vim /etc/my.cnf
slave-parallel-type=LOGICAL_CLOCK   # 并行的类型
slave-parallel-workers=5  # 开启多少个线程
master_info_repository=TABLE  # maste.info和relay.info是以表的形式存储的
relay_log_info_repository=TABLE   # 存储日志以表的形式
relay_log_recovery=ON  # 支持恢复
[root@server2 ~]# systemctl restart mysqld
[root@server2 ~]# mysql -p
Enter password: 
mysql> show processlist;

在这里插入图片描述


八、实现MySQL全同步复制(组复制)

1、mysql的全同步复制(组复制)的基础知识
组复制是一种可用于实现容错系统的技术。 复制组是一个通过消息传递相互交互的 server 集群。通信层提供了原子消息(atomic message)和完全有序信息交互等保障机制。 这些是非常强大的功能,我们可以据此架构设计更高级的数据库复制解决方案。
2、mysql组复制分类:
  • 单主模式:会自动选主,所有更新操作都在主上进行;
    单主模式中,只有设置为primary的节点有写入能力,其他节点是只读节点。这种模式下,集群中的primary节点出现故障时会进行重新选举的过程:
    在这里插入图片描述
    因为其余secondary节点没有写的能力,因此需要重新选出一个primary节点来提供服务。这个选举的过程是Paxos协议保证的。

现在大部分的分布式集群是基于Raft协议实现的,Raft协议只会支持单主模式的实现,因此现存的大部分分布式数据库系统,都是单点写入,即便是实现了分片,在每一个片中也只是一个节点在提供写服务。

  • 多主模式
    多主模式中,集群中所有的节点都可以是priamry,这样也就不存在单主模式中的选举的概念了,那么多主模式的故障处理应该是这样的:
    在这里插入图片描述
3、特点:
  • 高一致性
    基于原生复制及 paxos 协议的组复制技术,并以插件的方式提供,提供一致数据安全保证;
  • 高容错性
    只要不是大多数节点坏掉就可以继续工作,有自动检测机制,当不同节点产生资源争用冲突时,不会出现错误,按照先到者优先原则进行处理,并且内置了自动化脑裂防护机制;
  • 高扩展性
    节点的新增和移除都是自动的,新节点加入后,会自动从其他节点上同步状态,直到新节点和其他节点保持一致,如果某节点被移除了,其他节点自动更新组信息,自动维护新的组信息;
  • 高灵活性
    有单主模式和多主模式,单主模式下,会自动选主,所有更新操作都在主上进行;
    多主模式下,所有 server 都可以同时处理更新操作。
    缺点: 组复制的效率很低
    当master节点写数据的时候,会等待所有的slave节点完成数据的复制,然后才继续往下进行
    组复制的每一个节点都可能是slave
4、什么样的应用场景适合用组复制?

1、弹性的数据库复制环境
组复制可以灵活的增加和减少集群中的数据库实例
2、高可用的数据库环境
组复制允许数据库实例宕机,只要集群中大多数服务器可用,则整个数据库服务可用
3、替代传统主从复制结构的数据库环境

5、基本原理
在mysql多主模式下,在组复制中通过Group Replication Protocol协议及Paxos协议,形成的整体高可用解决方案 同时增加了certify的概念,负责检查事务是否允许提交,是否与其它事务存在冲突,Group Replication是由多个节点共同组成一个数据库集群,每个节点都可以单独执行事务,但是read-write(rw)的操作只有在组内验证后才可以commit,Read-only (RO)事务是不需要验证可以立即执行,当一个事务在一个节点上提交之前,会在组内自动进行原子性的广播,告知其他节点变更了什么内容/执行了什么事务,然后为该事物建立一个全局的排序,最终,这意味着所有的服务器都以相同的顺序接收相同的事务集。因此,所有服务器都按照相同的顺序应用相同的变更集,因此它们在组中保持一致

在这里插入图片描述

实验环境

主机名IP作用
server 1172.25.70.1master节点
server2172.25.70.2master节点
server3172.25.70.3master节点

恢复环境,准备重新初始化:将半同步的数据全部删除,否则影响组复制
恢复server1环境

[root@server1 ~]# systemctl stop mysqld.servic
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# ls
[root@server1 mysql]# rm -fr *
[root@server1 mysql]# ps ax | grep mysqld # 确保没有mysqld进程

在这里插入图片描述

恢复server2环境

[root@server2 ~]# systemctl stop mysqld.service
[root@server2 ~]# cd /var/lib/mysql/auto.cnf
[auto]
server-uuid=1598e8c5-df26-11e9-bd1f-525400c791eb  # 随机生成uuid
[root@server2 ~]# cd /var/lib/mysql/
[root@server2 mysql]# rm -fr *
在server1(master)上
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# vim /etc/my.cnf
server_id=1
gtid_mode=ON    # 启用二进制日志
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON   # 开启日志同步
log_bin=binlog
binlog_format=ROW  # 二进制日志格式

transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="1598e8c5-df26-11e9-bd1f-525400c791eb  " #组复制的名称与master的上任何一个名字不一样; 这是随机生成的,但是一旦设定,uuid就是确定的
loose-group_replication_start_on_boot=off  # 开机不启动
loose-group_replication_local_address= "172.25.70.1:33061" # 绑定本地的172.25.70.12以及33061端口接受其他组成员的连接
loose-group_replication_group_seeds= "172.25.70.1:33061,172.25.70.2:33061,172.25.70.3:33061"  # 组复制的成员
loose-group_replication_bootstrap_group=off  # 配置不自动引导组
loose-group_replication_ip_whitelist="127.0.0.1,172.25.70.0/24" #组复制设置白名单;# 允许网段
loose-group_replication_enforce_update_everywhere_checks=ON   # 更新检测
loose-group_replication_single_primary_mode=OFF #单用户模式;# 设置组自动选择一个 server 来处理读/写工作。

在这里插入图片描述

[root@server1 mysql]# vim /var/log/mysqld.log #重启mysql服务报错,是因为mysql.user不存在
[root@server1 mysql]# rm -fr *  #解决方法,直接删除,重启
[root@server1 mysql]# systemctl start mysqld.service  # 开启数据库
[root@server1 mysql]# grep password /var/log/mysqld.log     # 获取初始密码

在这里插入图片描述

[root@server1 mysql]# mysql -uroot -p
Enter password: 
mysql> alter user root@localhost identified by 'Wang+123';  # 修改本地用户密码
mysql> SET SQL_LOG_BIN=0;  # 关闭二进制日志,避免在从服务上复制
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Wang+123';  # 赋予所有用户密码
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';   # 授权
mysql> FLUSH PRIVILEGES;  #刷新授权表
mysql> SET SQL_LOG_BIN=1;  # 开启日志
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Wang+123' FOR CHANNEL 'group_replication_recovery';  # 配置组用户
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';   # 安装plugin插件
mysql> SET GLOBAL group_replication_bootstrap_group=ON;  #这句只有server1,在第一次执行引导组的时候执行
mysql> START GROUP_REPLICATION;  # 开启组复制
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
mysql> SELECT * FROM performance_schema.replication_group_members;  # 查看组复制成员

##只有是online才算设置成功
在这里插入图片描述

mysql> CREATE DATABASE test;  # 创建数据库
mysql> use test;   
Database changed
mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);  # 创建表
mysql> INSERT INTO t1 VALUES (1, 'Luis');
mysql> SELECT * FROM t1;

在这里插入图片描述

在server2(master)上
[root@server2 mysql]# vim /etc/my.cnf
server_id=2
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW

transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="1598e8c5-df26-11e9-bd1f-525400c791eb"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "172.25.70.2:33061"
loose-group_replication_group_seeds= "172.25.70.1:33061,172.25.70.2:33061,172.25.70.3:33061"
loose-group_replication_bootstrap_group=off
loose-group_replication_ip_whitelist="127.0.0.1,172.25.70.0/24"
loose-group_replication_enforce_update_everywhere_checks=ON
loose-group_replication_single_primary_mode=OFF

在这里插入图片描述

[root@server2 mysql]# systemctl start mysqld.service
[root@server2 mysql]# cat /var/log/mysqld.log  | grep password

在这里插入图片描述

[root@server1 mysql]# mysql -uroot -p
Enter password: 
mysql> alter user root@localhost identified by 'Wang+123';  # 修改本地用户密码
mysql> SET SQL_LOG_BIN=0;  # 关闭二进制日志,避免在从服务上复制
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Wang+123';  # 赋予所有用户密码
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';   # 授权
mysql> FLUSH PRIVILEGES;  #刷新授权表
mysql> SET SQL_LOG_BIN=1;  # 开启日志
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Wang+123' FOR CHANNEL 'group_replication_recovery';  # 配置组用户
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';   # 安装plugin插件
mysql> SHOW PLUGINS;
mysql> START GROUP_REPLICATION;  # 有冲突,开启失败

在这里插入图片描述

mysql> STOP GROUP_REPLICATION;
mysql> set global group_replication_allow_local_disjoint_gtids_join=on;
mysql> reset master;
mysql> START GROUP_REPLICATION;
在server1上查看:
mysql> SELECT * FROM performance_schema.replication_group_members;  # 查看组复制成员

在这里插入图片描述

在server3上
[root@server3 ~]# cd mysql_inst/
[root@server3 mysql_inst]# ls
mysql-community-client-5.7.24-1.el7.x86_64.rpm  mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm  mysql-community-server-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
[root@server3 mysql_inst]# yum install -y *
[root@server3 mysql_inst]# vim /etc/my.cnf
server_id=3
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW

transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="1598e8c5-df26-11e9-bd1f-525400c791eb"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "172.25.70.3:33061"
loose-group_replication_group_seeds= "172.25.70.1:33061,172.25.70.2:33061,172.25.70.3:33061"
loose-group_replication_bootstrap_group=off
loose-group_replication_ip_whitelist="127.0.0.1,172.25.70.0/24"
loose-group_replication_enforce_update_everywhere_checks=ON
loose-group_replication_single_primary_mode=OFF

在这里插入图片描述

[root@server3 mysql_inst]# systemctl start mysqld
[root@server3 mysql_inst]# grep password /var/log/mysqld.log

在这里插入图片描述

[root@server1 mysql]# mysql -uroot -p
Enter password: 
mysql> alter user root@localhost identified by 'Wang+123';  # 修改本地用户密码
mysql> SET SQL_LOG_BIN=0;  # 关闭二进制日志,避免在从服务上复制
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Wang+123';  # 赋予所有用户密码
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';   # 授权
mysql> FLUSH PRIVILEGES;  #刷新授权表
mysql> SET SQL_LOG_BIN=1;  # 开启日志
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='Wang+123' FOR CHANNEL 'group_replication_recovery';  # 配置组用户
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';   # 安装plugin插件
mysql> STOP GROUP_REPLICATION;
mysql> set global group_replication_allow_local_disjoint_gtids_join=on;
mysql> SHOW PLUGINS;
mysql> START GROUP_REPLICATION;  
mysql> SELECT * FROM performance_schema.replication_group_members; # 查看组成员成员状态

在这里插入图片描述

在server1上查看:
mysql> SELECT * FROM performance_schema.replication_group_members;  # 查看组复制成员

在这里插入图片描述

在server3上
mysql> show databases;    # 直接查看,把master1上的数据同步成功

在这里插入图片描述

mysql> use test;
Database changed
mysql> show tables;

在这里插入图片描述

在server1(master2)上查看,也同步成功
mysql> use test;
Database changed
mysql> select * from t1;

在这里插入图片描述

在任意一方插入数据都可以成功,也都能查看到插入的数据,该实验在server3上插入
mysql> INSERT INTO t1 VALUES (2, ‘lala');
mysql>  INSERT INTO t1 VALUES (3, ‘haha');
在server1上查看
mysql> select * from t1;

在这里插入图片描述

组复制实验完成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值