Mysql MGR简介与单主模式搭建初体验

Group Replication是MySQL官方发布的一个开源插件,用来实现MySQL高可用集群。

2016.12月Group Replication的第一个GA版本正式发布于MySQL5.7.17中。想要使用Group Replication功能,需要安装MySQL5.7.17及以后的版本。

 

组的概念:


Group Replication插件中有组(group)的概念,被Group Replication插件连接在一起的MySQL服务器是一个高可用组,组内的MySQL服务器被称为成员(Member)。

Group Replication在传输数据时,使用了paxos协议,在分布式环境下面保证了数据传输的一致性和原子性。

Paxos是用于一种分布式系统并且具有容错性的一致性算法,是目前业界公认能解决分布式系统一致性问题的算法之一。还有其他解决分布式一致性的算法如raft算法。

 

服务模式:单主模式   多主模式

单主模式如图:

当主宕机之后,会自动选举新的主,无需人工干预。当db01宕机了如硬件故障,那么它会在db02,db03上面选举出一个主来对外提供服务,整个故障转移过程不需要人工干预。

使用了paxos协议保证了db1-3上的数据的一致性,mysql和Oracle是不一样的,Oracle集群是通过共享存储ASM来共享数据文件,通过锁来解决数据的并发访问。而mysql不共享任何东西所有的数据都copy了一份,所以要通过paxos协议来保证数据一致性。

多主模式:db1-3都是可读可写的,在任意的节点做读写都可以。

 

 

环境准备(搭建单主模式)


主机名

IP

系统

数据库版本

db01

192.168.179.102

CentOS7.4

5.7.30

db02

192.168.179.103

CentOS7.4

5.7.30

db03

192.168.179.104

CentOS7.4

5.7.30

确保你都防火墙和selinux以及iptables是关闭的 

[root@localhost ~]# systemctl status firewalld
?.firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 


[root@localhost ~]# getenforce 
Disabled

 修改主机名,并且配置/etc/hosts

#永久修改主机名,在你的三台机器上分别修改主机名然后退出当前shell再重新登入
[root@localhost ~]# hostnamectl   set-hostname  db01
[root@localhost ~]# hostnamectl   set-hostname  db02
[root@localhost ~]# hostnamectl   set-hostname  db03

#配置三台机器的/etc/hosts,添加如下内容
[root@localhost mysql]# vim /etc/hosts
192.168.179.102 db01
192.168.179.103 db02
192.168.179.104 db03

以上步骤在192.168.179.102-104分别设置

mysql环境检查

#确保你的mysql版本>5.7.17
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.30    |
+-----------+

#如果你是在虚拟机环境克隆的MySQL,注意个MySQL uudi必须是不一样的
[root@localhost ~]# cd /var/lib/mysql
[root@localhost mysql]# cat auto.cnf  --保证每个MySQL的uudi是不一样的
[auto]
server-uuid=18f5da07-a096-11ea-8c70-000c290e1abf
或者这样登入MySQL查看uudi
mysql> show variables like "%server_uuid%";
+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_uuid   | 18f5da07-a096-11ea-8c70-000c290e1abf |
+---------------+--------------------------------------+

如果需要改变你的uuid可以使用select uuid();这条语句,将产生的该值设置到/var/lib/mysql/auto.cnf中,然后重启MySQL,这是针对克隆的虚拟机。

 

配置主节点db01:192.168.179.102


 修改my.cnf添加如下配置:

在你my.cnf配置文件下面添加如下内容:
[mysqld]
validate_password = OFF
character_set_server = utf8mb4  #字符集
server_id = 101  #保证每个MySQL服务器id不一致

gtid_mode = ON  #做MGR必须要将该功能打开
enforce_gtid_consistency = ON #gtid_mode enforce_gtid_consistency 这两个选项是开启gtid都要设置的

master_info_repository = TABLE #默认情况下是存放在文件上面,MGR要求将master.info元数据保存在系统表中
relay_log_info_repository = TABLE #将relay.info元数据保存在系统表中

binlog_checksum = NONE #禁用二进制日志事件校验
log_slave_updates = ON #级联复制A->B->C,

log_bin = mysql-bin
binlog_format= ROW #以行的格式记录

transaction_write_set_extraction = XXHASH64 #使用哈希算法
loose-group_replication_group_name = '5a421130-2674-11ea-bbce-00505639ee45' #所有节点使用相同组名
loose-group_replication_start_on_boot = off #不自动启用组复制集群
loose-group_replication_local_address = 'db01:33061' #本机地址和端口,节点间通讯地址,不使用3306使用33061
loose-group_replication_group_seeds = 'db01:33061,db02:33061,db03:33061' #组中成员
loose-group_replication_bootstrap_group = off #不启用引导组,手动引导启动


#注意:前缀loose-,如果不加上loose-会报错

查看MySQL默认配置并且重启MySQL让上面配置生效 

mysql> show variables like '%repository%';  #没做MGR,可以看到是存放在文件当中
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| master_info_repository    | FILE  |
| relay_log_info_repository | FILE  |
+---------------------------+-------+
mysql> show variables like 'binlog_checksum';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| binlog_checksum | CRC32 |
+-----------------+-------+
mysql> show variables like 'log_slave_updates';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| log_slave_updates | OFF   |
+-------------------+-------+

修改完my.cnf配置先不要重启,去mysql里面看看,可以看到配置文件里面修改了MySQL默认配置值
[root@db01 ~]# systemctl restart mysqld   查看完之后重启MySQL

mysql> show variables like  '%group_replication%';
Empty set (0.04 sec)
#没有显示任何东西,这个需要安装插件才能显示出来,所以前面需要添加loose

 查看MySQL插件和安装组复制插件

#看看MySQL安装了插件路径
[root@localhost ~]# rpm -ql mysql-community-server | grep plugin
/usr/bin/mysql_plugin
/usr/lib64/mysql/plugin
/usr/lib64/mysql/plugin/adt_null.so

#看看MySQL为我们提供了哪些插件
[root@localhost ~]# cd /usr/lib64/mysql/plugin/
[root@localhost plugin]# ls  这些.so文件就是插件
adt_null.so                         group_replication.so  libmemcached.so     mysqlx.so           validate_password.so
authentication_ldap_sasl_client.so  ha_example.so         libpluginmecab.so   rewrite_example.so  version_token.so
auth_socket.so                      innodb_engine.so      locking_service.so  rewriter.so
connection_control.so               keyring_file.so       mypluglib.so        semisync_master.so
debug                               keyring_udf.so        mysql_no_login.so   semisync_slave.so

validate_password.so 这个是验证密码插件
semisync_master.so semisync_slave.so  半同步复制插件
group_replication.so 我们需要安装的是该插件,需要进入MySQL安装该插件



mysql> show plugins;
| validate_password          | DISABLED | VALIDATE PASSWORD  | validate_password.so | GPL     |
可以看到将该插件关掉了,因为我们修改配置文件有这条validate_password = OFF这样会禁用validate_password.so插件

#安装组复制插件
mysql> install plugin group_replication soname 'group_replication.so';
Query OK, 0 rows affected (0.19 sec)

# 可以看到该插件已经安装成功了
mysql> show plugins; 

| group_replication          | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |

#这个时候可以看到插件将配置信息展示出来了
mysql> show variables like '%group_replication%';
+----------------------------------------------------+--------------------------------------+
| Variable_name                                      | Value                                |
+----------------------------------------------------+--------------------------------------+
| group_replication_allow_local_disjoint_gtids_join  | OFF                                  |
| group_replication_allow_local_lower_version_join   | OFF                                  |
| group_replication_auto_increment_increment         | 7                                    |
| group_replication_bootstrap_group                  | OFF                                  |
| group_replication_components_stop_timeout          | 31536000                             |
| group_replication_compression_threshold            | 1000000                              |
| group_replication_enforce_update_everywhere_checks | OFF                                  |
| group_replication_exit_state_action                | READ_ONLY                            |
| group_replication_flow_control_applier_threshold   | 25000                                |
| group_replication_flow_control_certifier_threshold | 25000                                |
| group_replication_flow_control_mode                | QUOTA                                |
| group_replication_force_members                    |                                      |
| group_replication_group_name                       | 5a421130-2674-11ea-bbce-00505639ee45 |
| group_replication_group_seeds                      | db01:33061,db02:33061,db03:33061     |

建立复制账号,因为主从通信需要通过账号信息去同步数据

set SQL_LOG_BIN=0;  #关闭binlog记录,为了是不让grant命令记录在bin log里面
grant replication slave on *.* to repl@'%' identified by '123456';
flush privileges;
set SQL_LOG_BIN=1;
change master to master_user='repl',master_password='123456' for channel 'group_replication_recovery';


#在执行上面sql之前查看一下数据库默认配置
mysql> show variables like '%SQL_LOG_BIN%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_log_bin   | ON    |
+---------------+-------+
mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name                   | Value                          |
+---------------------------------+--------------------------------+
| log_bin                         | ON                             |
| log_bin_basename                | /var/lib/mysql/mysql-bin       |
| log_bin_index                   | /var/lib/mysql/mysql-bin.index |



在db01 192.168.179.102上执行如下语句
mysql> set SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on *.* to repl@'%' identified by '123456';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> set SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)


#执行该sql语句会记录在表slave_master_info里面
mysql> change master to master_user='repl',master_password='123456' for channel 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)

| Note  | 1760 | Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

master_info_repository = TABLE 
relay_log_info_repository = TABLE 
因为前面配置了
mysql> use mysql;
mysql> select User_name,User_password,Channel_name from slave_master_info;
+-----------+---------------+----------------------------+
| User_name | User_password | Channel_name               |
+-----------+---------------+----------------------------+
| repl      | 123456        | group_replication_recovery |
+-----------+---------------+----------------------------+

启动db01上的group replication集群

set global group_replication_bootstrap_group=ON;  将db10设置为组里面的主库
start group_replication;
set global group_replication_bootstrap_group=OFF;

#db01 192.168.179.102上执行
mysql> set global group_replication_bootstrap_group=ON; 
Query OK, 0 rows affected (0.00 sec)
mysql> start group_replication;
Query OK, 0 rows affected (2.31 sec)
mysql> set global group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

查看集群状态

#如果后面两个从节点db02,db03加入就会有三个记录,现在因为只启动了一个主节点所以一条记录
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 18f5da07-a096-11ea-8c70-000c290e1abf | db01        |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
1 row in set (0.00 sec)

mysql>  show variables like "%server_uuid%";
+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_uuid   | 18f5da07-a096-11ea-8c70-000c290e1abf |
+---------------+--------------------------------------+
1 row in set (0.01 sec)

至此主节点配置完毕,下面就是让db02,db03加入到集群当中作为slave节点

 

配置从节点db02:192.168.179.103让其加入集群


 和上面主库配置一样修改my.cnf配置文件

[mysqld]
validate_password = OFF
character_set_server = utf8mb4
server_id = 102  #在集群环境要保证id唯一,需要修改
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 = mysql-bin
binlog_format= ROW
transaction_write_set_extraction = XXHASH64 #在一个库使用,那么所有库都相同配置
loose-group_replication_group_name = '5a421130-2674-11ea-bbce-00505639ee45'
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = 'db02:33061' #改为db02
loose-group_replication_group_seeds = 'db01:33061,db02:33061,db03:33061'
loose-group_replication_bootstrap_group = off


修改完my.cnf重启MySQL
[root@db02 ~]# systemctl restart mysqld

#和主库一样安装插件
mysql> install plugin group_replication soname 'group_replication.so';
Query OK, 0 rows affected (0.22 sec)

#和主库一样建立复制账号
mysql> grant replication slave on *.* to repl@'%' identified by '123456';
Query OK, 0 rows affected, 1 warning (0.04 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
mysql> set SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to master_user='repl',master_password='123456' for channel 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)


读节点加入组的时候,start group_replication抛出了下面的错误。基本碰到这个错误,你离搭建成功就不远了。

2020-05-29T07:56:30.064556Z 0 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 89328c79-f730-11e6-ab63-782bcb377193:1-2 > Group transactions: 7c744904-f730-11e6-a72d-782bcb377193:1-4'
2020-05-29T07:56:30.064580Z 0 [ERROR] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'
2020-05-29T07:56:30.064587Z 0 [Note] Plugin group_replication reported: 'To force this member into the group you can use the group_replication_allow_local_disjoint_gtids_join option'
可以很明显看到日志中已经提示了,需要设置参数,也就是兼容加入组。group_replication_allow_local_disjoint_gtids_join设置完成后运行start group_replication即可。

#为了避免上面搭建集群失败需要在从节点执行
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
Query OK, 0 rows affected, 1 warning (0.01 sec)

启动db02上的group replication
mysql>  start group_replication;
Query OK, 0 rows affected, 1 warning (6.07 sec)

#可以看到db02成功加入集群
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 18f5da07-a096-11ea-8c70-000c290e1abf | db01        |        3306 | ONLINE       |
| group_replication_applier | dfe895a8-a0df-11ea-bb7d-000c296190c1 | db02        |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+

下面的db03如法炮制,只需要修改一下my.cnf,其他步骤一模一样

 

配置从节点db03:192.168.179.104让其加入集群


#修改my.cnf配置文件
[mysqld]
validate_password = OFF
character_set_server = utf8mb4
server_id = 103  #修改
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 = mysql-bin
binlog_format= ROW
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = '5a421130-2674-11ea-bbce-00505639ee45'
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = 'db03:33061'  #修改
loose-group_replication_group_seeds = 'db01:33061,db02:33061,db03:33061'
loose-group_replication_bootstrap_group = off


#安装插件
mysql> install plugin group_replication soname 'group_replication.so';
Query OK, 0 rows affected (0.08 sec)

#建立复制账号
mysql> set SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.01 sec)
mysql> grant replication slave on *.* to repl@'%' identified by '123456';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> set SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to master_user='repl',master_password='123456' for channel 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)


#启动db03上的group replication
mysql> start group_replication;
Query OK, 0 rows affected, 1 warning (3.52 sec)

#查看集群状态
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 18f5da07-a096-11ea-8c70-000c290e1abf | db01        |        3306 | ONLINE       |
| group_replication_applier | 7d3e894a-a0a9-11ea-82f8-000c29a7fff7 | db03        |        3306 | ONLINE       |
| group_replication_applier | dfe895a8-a0df-11ea-bb7d-000c296190c1 | db02        |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

至此集群搭建完毕

 

测试


(1)MGR集群中,只支持innodb引擎的表,并且该表必须有显式的主键,或者非Null的唯一键,否则即使能够创建表,也无法向表中写入数据。 

#在db01上测试
mysql> use testdb;
Database changed
mysql> create table tbs01(id int, name varchar(20));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into tbs01 values(1, 'fxkt');
ERROR 3098 (HY000): The table does not comply with the requirements by an external plugin.
mysql> create table tbs02(id int primary key, name varchar(20));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into tbs02 values(1, 'fxkt');
Query OK, 1 row affected (0.01 sec)


#db02上可以看到数据同步过来了
mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from tbs02;
+----+------+
| id | name |
+----+------+
|  1 | fxkt |
+----+------+
1 row in set (0.01 sec)

(2)主库可读可写,从库只读

db01上
mysql> show variables like '%read_only%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_read_only      | OFF   |
| read_only             | OFF   |
| super_read_only       | OFF   |
| transaction_read_only | OFF   |
| tx_read_only          | OFF   |
+-----------------------+-------+
5 rows in set (0.01 sec)


db02/03上
mysql> show variables like '%read_only%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_read_only      | OFF   |
| read_only             | ON    |
| super_read_only       | ON    |
| transaction_read_only | OFF   |
| tx_read_only          | OFF   |
+-----------------------+-------+
5 rows in set (0.04 sec)

 

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