一:个人看法
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; 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