Mysql的组复制简介
组复制简介
- 组复制分单主模式和多主模式,mysql 的复制技术仅解决了数据同步的问题,如果 master 宕机,意味着数据库管理员需要介入,应用系统可能需要修改数据库连接地址或者重启才能实现。组复制在数据库层面上做到了,只要集群中大多数主机可用,则服务可用。
- 单主模型:从复制组众多个MYSQL节点中自动选举一个master节点,只有master节点可以写,其它节点自动设置为只读。当master节点故障时,会自动选举一个新的master节点,选举成功后,它将设置为可写,其它的slave将指向这个新的master。
- 多主模型:复制组中的任何一个节点都可以写,因此没有master和slave的概念,只要突然故障的节点的数量不太多这个多主模就能继续使用。
组复制原理
- 组复制由多个mysql服务器组成,并且组中的每一个mysql服务成员可以独立的执行事务。但是所有的读写事务只有在冲突检测成功后才会提交,只读事务不需要冲突检测,可以立即提交。
- 对于任何读写事务,提交操作并不是由始发服务单向决定的,而是由组来决定是否提交。
- 在始发mysql服务上,当事务准备好要提交时,该主机会广播写入值即已改变的行和对应的写入集及已更新的行的唯一标识符。然后会为该事务建立一个全局的顺序。最终,所有的server成员以相同的顺序接收同一组事务。所有的server成员以相同的顺序应用相同的更改,以保证组内一致。
实验环境
主机名(ip) | 功能 |
---|---|
172.25.24.1 | master |
172.25.24.2 | slave1 |
172.25.24.3 | slave2 |
单组复制实验过程
server1
- 查看server1的uuid。
[root@server1 ~]# cat /var/lib/mysql/auto.cnf
[auto]
server-uuid=ba2ea735-b17c-11e9-a9e5-5254008d153c
- 因为在此实验之前,我做了基于gtid半同步的实验,server1主机中已有数据,所以得先将数据库恢复到初始状态(关闭服务,删除数据库目录下的内容,开启服务,利用生成的密码初始化数据库)。这些操作会生成一个新的uuid。
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# systemctl stop mysqld
[root@server1 mysql]# rm -fr *
[root@server1 mysql]# ls
[root@server1 mysql]# systemctl start mysqld
[root@server1 mysql]# cat /var/log/mysqld.log | grep password
[root@server1 mysql]# mysql -uroot -p
mysql> alter user root@localhost identified by 'Wsp+123ld';
- 编写配置文件,添加组复制的内容。
[root@server1 ~]# vim /etc/my.cnf
29 server_id=1
30 gtid_mode=ON
31 enforce_gtid_consistency=ON
32 master_info_repository=TABLE
33 relay_log_info_repository=TABLE
34 binlog_checksum=NONE
35 log_slave_updates=ON
36 log_bin=binlog
37 binlog_format=ROW
38
39 transaction_write_set_extraction=XXHASH64 #指定server必须为每个事务收集写集合,并使用哈希算法将其编码为散列。
40 loose_group_replication_group_name="ba2ea735-b17c-11e9-a9e5-5254008d153c" #对创建的组命名。
41 loose_group_replication_start_on_boot=off #不自动启动组复制
42 loose_group_replication_local_address= "172.25.24.1:33061" #本地端口33061实现成员连接
43 loose_group_replication_group_seeds= "172.25.24.1:33061,172.25.24.2:33061,172.25.24.3:33061"
44 loose_group_replication_bootstrap_group=off #是否自动引导组
45 loose_group_replication_ip_whitelist="127.0.0.1,172.25.24.0/24"
46 loose_group_replication_enforce_update_everywhere_checks=ON #打开检查及更新
47 loose_group_replication_single_primary_mode=OFF #设置组自动选择一个server来处理读写工作
[root@server1 ~]# systemctl restart mysqld
- 启动组复制,完成后查看状态,若为online则组复制添加成功。
mysql> SET SQL_LOG_BIN=0; #在建立用户之前先关闭二进制日志,建立完成之后再打开。
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Wsp+123ld'; #创建用户
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='Wsp+123ld' FOR CHANNEL 'group_replication_recovery'; #如果需要改变master时,通过该通道group_replication_recovery给其master的用户名和密码
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so'; #安装组复制的插件
mysql> SET GLOBAL group_replication_bootstrap_group=ON; #只在master上进行此操作,即master是组复制的发起者,当组复制打开之后将其关闭。
mysql> START GROUP_REPLICATION; #开启组复制
mysql> SET GLOBAL group_replication_bootstrap_group=OFF; #关闭
mysql> SELECT * FROM performance_schema.replication_group_members; #组复制添加完成之后查看状态
- 创建数据库和表,插入数据,方便后续测试。
mysql> CREATE DATABASE test;
mysql> USE test;
mysql> CREATE TABLE t1(c1 INT PRIMARY KEY,c2 TEXT NOT NULL);
mysql> INSERT INTO t1 VALUES(1,'linux');
mysql> SELECT * FROM t1;
+----+-------+
| c1 | c2 |
+----+-------+
| 1 | linux |
+----+-------+
server2
- 因为server2在实验之前也有数据,所以同样需要先删除数据,进行安全初始化,不再赘述。
[root@server2 ~]# cd /var/lib/mysql
[root@server2 mysql]# systemctl stop mysqld
[root@server2 mysql]# rm -fr *
[root@server2 mysql]# ls
[root@server2 mysql]# systemctl start mysqld
安全初始化:
[root@server2 mysql]# cat /var/log/mysqld.log | grep password
[root@server2 mysql]# mysql -uroot -p
mysql> alter user root@localhost identified by 'Wsp+123ld';
- 编辑配置文件,加入组复制的内容,重启服务。
[root@server2 mysql]# vim /etc/my.cnf
29 server_id=2 #改
30 gtid_mode=ON
31 enforce_gtid_consistency=ON
32 master_info_repository=TABLE
33 relay_log_info_repository=TABLE
34 binlog_checksum=NONE
35 log_slave_updates=ON
36 log_bin=binlog
37 binlog_format=ROW
39 transaction_write_set_extraction=XXHASH64
40 loose_group_replication_group_name="ba2ea735-b17c-11e9-a9e5-5254008d153c"
41 loose_group_replication_start_on_boot=off
42 loose_group_replication_local_address= "172.25.24.2:33061" #改
43 loose_group_replication_group_seeds= "172.25.24.1:33061,172.25.24.2:33061,172.2 5.24.3:33061"
44 loose_group_replication_bootstrap_group=off
45 loose_group_replication_ip_whitelist="127.0.0.1,172.25.24.0/24"
46 loose_group_replication_enforce_update_everywhere_checks=ON
47 loose_group_replication_single_primary_mode=OFF
[root@server2 mysql]# systemctl restart mysqld
- 启动组复制。
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Wsp+123ld';
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='Wsp+123ld' FOR CHANNEL 'group_replication_recovery';
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
mysql> START GROUP_REPLICATION;
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.
- 发现有报错,我们查看日志。
[root@server2 mysql]# vim /var/log/mysqld.log
- 按照日志的提示进行解决,server2成功开启组复制。
[root@server2 mysql]# mysql -uroot -p
mysql> set global group_replication_allow_local_disjoint_gtids_join=on;
mysql> START GROUP_REPLICATION;
- 查看两个节点的状态,都是online。
server3
- 在server1将安装包发给server3
[root@server1 ~]# scp mysql-* server3:/root/
- server3安装,开启服务,获取密码 ,初始化,修改配置文件,不再赘述。
[root@server3 ~]# yum install * -y
[root@server3 ~]# systemctl start mysqld
[root@server3 ~]# grep password /var/log/mysqld.log
[root@server3 ~]# mysql -uroot -p
mysql> alter user root@localhost identified by 'Wsp+123ld';
mysql> show databases;
[root@server3 ~]# vim /etc/my.cnf
29 server_id=3 #改
30 gtid_mode=ON
31 enforce_gtid_consistency=ON
32 master_info_repository=TABLE
33 relay_log_info_repository=TABLE
34 binlog_checksum=NONE
35 log_slave_updates=ON
36 log_bin=binlog
37 binlog_format=ROW
38
39 transaction_write_set_extraction=XXHASH64
40 loose_group_replication_group_name="ba2ea735-b17c-11e9-a9e5-5254008d153c"
41 loose_group_replication_start_on_boot=off
42 loose_group_replication_local_address= "172.25.24.3:33061" #改
43 loose_group_replication_group_seeds= "172.25.24.1:33061,172.25.24.2:33061,172.25.24.3:33061"
44 loose_group_replication_bootstrap_group=off
45 loose_group_replication_ip_whitelist="127.0.0.1,172.25.24.0/24"
46 loose_group_replication_enforce_update_everywhere_checks=ON
47 loose_group_replication_single_primary_mode=OFF
- 启动组复制。
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'Wsp+123ld';
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='Wsp+123ld' FOR CHANNEL 'group_replication_recovery';
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
mysql> START GROUP_REPLICATION;
ERROR 3092 (HY000): The server is not configured properly to be an active member of the group. Please see more details on error log.
mysql> set global group_replication_allow_local_disjoint_gtids_join=on;
mysql> START GROUP_REPLICATION;
- server3查看启动组复制有没有成功。
测试
- 在server3主机向数据库中插入数据。
mysql> use test;
mysql> select * from t1;
+----+-------+
| c1 | c2 |
+----+-------+
| 1 | linux |
+----+-------+
mysql> insert into t1 values (2,'redhat');
mysql> select * from t1;
+----+--------+
| c1 | c2 |
+----+--------+
| 1 | linux |
| 2 | redhat |
+----+--------+
- server1查看写入的数据
mysql> select * from test.t1;
+----+--------+
| c1 | c2 |
+----+--------+
| 1 | linux |
| 2 | redhat |
+----+--------+
- server2:停止组复制(相当于被提出集群。)
mysql> STOP GROUP_REPLICATION;
- server1查看,并插入数据。
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 764512a2-b191-11e9-91c9-5254008d153c | server1 | 3306 | ONLINE |
| group_replication_applier | 963bf139-b195-11e9-9c9e-525400d5afcf | server3 | 3306 | ONLINE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
- server1插入数据。
mysql> use test;
mysql> insert into t1 values(3,'zyw');
mysql> select * from t1;
+----+--------+
| c1 | c2 |
+----+--------+
| 1 | linux |
| 2 | redhat |
| 3 | zyw |
+----+--------+
- server3查看。
mysql> select * from t1;
+----+--------+
| c1 | c2 |
+----+--------+
| 1 | linux |
| 2 | redhat |
| 3 | zyw |
+----+--------+
- server2在再次开启组复制之前查看以及在开启之后查看:
mysql> use test;
mysql> select * from t1;
mysql> START GROUP_REPLICATION; 再开启组复制查看:
mysql> select * from t1;
注意:
- server1,server2,server3配置文件
/etc/my.cnf
里的uuid,和每个节点配置文件/var/lib/mysql/auto.cnf
里的UUID都不一样才行。
reset master 清除master信息
reset slave 清除当前节点的日志
show plugins 看插件有没有装过
开启组复制后某一节点Recovery状态的原因以及解决办法
-
原因:
1.主机解析有问题
2.UUID
3.数据不同步 -
解决办法:
1.主库备份所有数据库,并将备份文件发给两个从库。mysqldump --all-databases --single-transaction --routines --triggers --events --host=127.0.0.1 --port=3306 --user=root --password=Wsp+123ld > zyw.db
2.从库如果开启了组复制,先停掉组复制。
3.reset master;(relay_log 作用是把主库的日志再执行一次,执行过就可以直接清空了。)
4.把备份导入mysql -p < zyw.db,如果报错,先关闭mysqld服务,再开启mysqld,再reset master。
5.不用删除/var/lib/mysql下的文件
6.查看此时的插件,没有重新安装插件
7.改变masterchange master to master_user='rpl_user',Master_Password='Wsp+123ld' For Channel 'group_replication_recovery';
8.再开启组复制。Start group_replication;