一:個人看法
Mysql Group Replication 隨着5.7發布3年了。作為技術愛好者。mgr 是繼 oracle database rac 之后。
又一個“真正” 的群集,怎么做到“真正” ? 怎么做到解決復制的延遲,怎么做到強數據一致性?基於全局的GTID就能解決? 圍繞這些問題進行了一些mgr 的實踐,
為未來的數據庫高可用設計多條選擇。
mysql5.7手冊17章可以看到其原理,網絡上也很多同志寫了關於其技術原理,這里自己對比rac理解下:
作為shared nothing (mgr)架構,其數據一致性實現較 shared everything(RAC) 架構要難,
MGR通過一致性(Paxos)協議,保證數據在復制組內的存活節點里是一致的,復制組內的各成員都可以進行讀寫,
其實現機制是,當某個實例發起事務提交時,會向組內發出廣播,由組內成員決議事務是否可以正常提交,
MGR在遇到事務沖突時(多節點同時修改同一行數據),會自動識別沖突,並根據提交時間讓先提交的事務成功執行,后提交的事務回滾,其原理示意圖如下:
對於 sharad nothing 架構,必須要了解分布式協議PAXOS,分布式狀態機 理論,而在這塊我翻閱了很多資料,發現其實並不是很成熟的。從上圖可以看出來MGR 的沖突檢測機制
類似於 rac 的gird 群集組件 也具備通告廣播的群集服務。但本質架構上有所不同。一切依賴於 復制組的軟件實現。如果這里出了問題,那么整個群集一致性難以得到保證。
二:搭建過程
這個過程比較粗糙,網絡上有不少寫的比較細的可以參考
create user repl@'%' identified by 'repl123'; grant replication slave on *.* to repl@'%'; change master to master_user='repl', master_password='repl123'
for channel 'group_replication_recovery'; select * from mysql.slave_relay_log_info\G install plugin group_replication soname 'group_replication.so'; set @@global.group_replication_bootstrap_group=on; ---->是否是Group Replication的引導節點,初次搭建集群的時候需要有一個節點設置為ON來啟動Group Replication start group_replication; set @@global.group_replication_bootstrap_group=off; select * from performance_schema.replication_group_members; create database test; use test; create table t1(id int); create table t2(id int)engine=myisam; create table t3(id int primary key)engine=myisam; --->不支持 create table t4(id int primary key);
3:其它節點加入組復制
change master to master_user='repl', master_password='repl123'
for channel 'group_replication_recovery'; install plugin group_replication soname 'group_replication.so'; set global group_replication_allow_local_disjoint_gtids_join=1; start group_replication;
注意:
一個節點加入組復制會有本地的事物產生,比如更改密碼,加入測試數據等。上述紅字可以可以規避上述事務,強制加入,也可以在本地事務開始之前進行
sql_log_bin=0; start transaction.......... sql_log_bin=1;
4:維護
任意一節點啟動,停止組復制。
start group_replication;
stop group_replication;
查看所有在線的組復制節點
select * from performance_schema.replication_group_members;
查看誰是主節點,單主模式下,能查出值,多主模式下無法查出。
select b.member_host the_master,a.variable_value master_uuid from performance_schema.global_status a join performance_schema.replication_group_members b on a.variable_value = b.member_id where variable_name='group_replication_primary_member';
+------------+--------------------------------------+
| the_master | master_uuid |
+------------+--------------------------------------+
| calldb3 | cc4958ae-a1cc-11e8-9334-00155d322c00 |
+------------+--------------------------------------+
三:vip的實施
mgr 並不提供vip 的概念。在單主模式下,必須啟用vip實現才能做到 HA 的作用,這里的策略網絡上也很多,我們基於keepalived 進行思考
要實現上述策略,考慮故障節點的情況
1:故障節點 mysql 實例崩潰,守護進程也不能拉起改實例,需要VIP 漂移。
2:故障節點系統崩潰,段時間無法進行恢復。需要VIP 漂移。
3:判定誰是主節點,vip就漂移到主節點
基於以上3點。keepalived 除了系統故障vip漂移的功能,還需要mysql 實例崩潰的判定主節點漂移功能
具體實現:
[root@calldb1 ~]# cat /etc/keepalived/keepalived.conf vrrp_script chk_mysql_port { script "/etc/keepalived/chk_mysql.sh" ---判斷實例存活 interval 2 weight -5 fall 2 rise 1 } vrrp_script chk_mysql_master { script "/etc/keepalived/chk_mysql2.sh" ---判斷主節點 interval 2 weight 10 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 88 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.0.100 } track_script { chk_mysql_port chk_mysql_master } }
判定腳本如下:
[root@calldb1 ~]# cat /etc/keepalived/chk_mysql.sh #!/bin/bash netstat -tunlp |grep mysql a=`echo $?` if [ $a -eq 1 ] ;then service keepalived stop fi
[root@calldb1 ~]# cat /etc/keepalived/chk_mysql2.sh #!/bin/bash host=`/data/mysql/bin/mysql -h127.0.0.1 -uroot -pxxx -e "SELECT * FROM performance_schema.replication_group_members WHERE MEMBER_ID = (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member')" |awk 'NR==2{print}'|awk -F" " '{print $3}'` host2=`hostname` if [ $host == $host2 ] ;then exit 0 else exit 1 fi
四:采坑的地方:
1:一個節點加入組的時候,因沒有種子的概念,那么它就是中心,所以要申明他是中心:
set @@global.group_replication_bootstrap_group=on;
2:如果沒有在etc/hosts 文件配置ip地址到主機的解析,那么組復制一直會出現:
2019-04-30T21:58:24.604720+08:00 42 [Note] Plugin group_replication reported: 'Retrying group recovery connection with another donor. Attempt 6/10' 2019-04-30T21:59:24.605458+08:00 42 [Note] 'CHANGE MASTER TO FOR CHANNEL 'group_replication_recovery' executed'. Previous state master_host='sanborn1', master_port= 3306, master_log_file='', master_log_pos= 4, master_bind=''. New state master_host='sanborn1', master_port= 3306, master_log_file='', master_log_pos= 4, master_bind=''. 2019-04-30T21:59:24.610029+08:00 42 [Note] Plugin group_replication reported: 'Establishing connection to a group replication recovery donor 75af6fe1-6a92-11e9-8bf8-005056a1d54e at sanborn1 port: 3306.' 2019-04-30T21:59:24.611927+08:00 50 [Warning] 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. 2019-04-30T21:59:24.645794+08:00 50 [ERROR] Slave I/O for channel 'group_replication_recovery': error connecting to master 'repl@sanborn1:3306' - retry-time: 60 retries: 1, Error_code: 2005 2019-04-30T21:59:24.645847+08:00 50 [Note] Slave I/O thread for channel 'group_replication_recovery' killed while connecting to master 2019-04-30T21:59:24.645861+08:00 50 [Note] Slave I/O thread exiting for channel 'group_replication_recovery', read up to log 'FIRST', position 4 2019-04-30T21:59:24.646002+08:00 42 [ERROR] Plugin group_replication reported: 'There was an error when connecting to the donor server. Please check that group_replication_recovery channel credentials and all MEMBER_HOST column values of performance_schema.replication_group_members table are correct and DNS resolvable.' 2019-04-30T21:59:24.646064+08:00 42 [ERROR] Plugin group_replication reported: 'For details please check performance_schema.replication_connection_status table and error log messages of Slave I/O for channel group_replication_recovery.' 2019-04-30T21:59:24.646271+08:00 42 [Note] Plugin group_replication reported: 'Retrying group recovery connection with another donor. Attempt 7/10'
直到脫離群集,狀態一直是recovering
mysql> select * from performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+ | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | +---------------------------+--------------------------------------+-------------+-------------+--------------+ | group_replication_applier | 75af6fe1-6a92-11e9-8bf8-005056a1d54e | sanborn1 | 3306 | ONLINE | | group_replication_applier | 8e091df0-6b4c-11e9-896b-005056a175f4 | sanborn2 | 3306 | RECOVERING | | group_replication_applier | ae657017-6b4c-11e9-8548-005056a1c149 | sanborn3 | 3306 | RECOVERING | +---------------------------+--------------------------------------+-------------+-------------+--------------+ 3 rows in set (0.01 sec)