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)

 

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