title: MySQL Group Replication-MGR集群部署及维护 #标题tags: #标签
date: 2022-01-02
categories: mysql # 分类
MySQL Group Replication(简称MGR)字面意思是mysql组复制的意思,但其实他是一个高可用的集群架构,暂时只支持mysql5.7和mysql8.0版本.
是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决方案,提供了高可用、高扩展、高可靠的MySQL集群服务.
也是mysql官方基于组复制概念并充分参考MariaDB Galera Cluster和Percona XtraDB Cluster结合而来的新的高可用集群架构.
MySQL Group Replication是建立在基于Paxos的XCom之上的,正因为有了XCom基础设施,保证数据库状态机在节点间的事务一致性,才能在理论和实践中保证数据库系统在不同节点间的事务一致性。
由一般主从复制概念扩展,多个节点共同组成一个数据库集群,事务的提交必须经过半数以上节点同意方可提交,在集群中每个节点上都维护一个数据库状态机,保证节点间事务的一致性。
优点:
- 高一致性,基于原生复制及paxos协议的组复制技术;
- 高容错性,有自动检测机制,当出现宕机后,会自动剔除问题节点,其他节点可以正常使用(类似zk集群),当不同节点产生资源争用冲突时,会按照先到先得处理,并且内置了自动化脑裂防护机制;
- 高扩展性,可随时在线新增和移除节点,会自动同步所有节点上状态,直到新节点和其他节点保持一致,自动维护新的组信息;
- 高灵活性,直接插件形式安装(5.7.17后自带.so插件),有单主模式和多主模式,单主模式下,只有主库可以读写,其他从库会加上super_read_only状态,只能读取不可写入,出现故障会自动选主;
缺点:- 还是太新,不太稳定,暂时性能还略差于PXC,对网络稳定性要求很高,至少是同机房做。
部署及配置MGR集群
环境准备
OS | 主机名 | IP | mysql版本 | 数据库端口 | MGR集群端口 |
---|---|---|---|---|---|
Cent OS 7.5 | centos-20-2 | 192.168.20.2 | 8.0.26 | 3306 | 33061 |
Cent OS 7.5 | centos-20-3 | 192.168.20.3 | 8.0.26 | 3306 | 33061 |
Cent OS 7.5 | centos-20-4 | 192.168.20.4 | 8.0.26 | 3306 | 33061 |
环境配置
所有节点必须对节点进行初始化配置,尤其是主机名解析,如果配置错误或不配置,则会直接导致MGR集群无法构建成功。
配置主机名解析
cat >> /etc/hosts << EOF
192.168.20.2 centos-20-2
192.168.20.3 centos-20-3
192.168.20.4 centos-20-4
EOF
修改系统限制
$ mv /etc/security/limits.conf{,.bak}
cat > /etc/security/limits.conf << EOF
* - nofile 655360
* - memlock unlimited
* - stack 655360
* - nproc unlimited
EOF
cat > /etc/sysctl.conf << EOF
kernel.sysrq = 0
kernel.core_uses_pid = 1
fs.file-max=655360
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
kernel.pid_max = 655360
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_max_tw_buckets = 10000
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_ecn = 0
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_max_orphans = 655360
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_mem = 65536 131072 262144
net.ipv4.udp_mem = 65536 131072 262144
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 16384 16777216
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.route.gc_timeout = 100
# 禁止icmp重定向报文
net.ipv4.conf.all.accept_redirects = 0
# 禁止icmp源路由
net.ipv4.conf.all.accept_source_route = 0
net.core.somaxconn = 65535
net.core.rmem_default = 8388608
net.core.wmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
vm.swappiness = 10
vm.overcommit_memory = 1
vm.max_map_count = 262144
EOF
sysctl -p
配置ntp时间同步
任意一台节点配置时间服务器,其他节点制定定时任务即可。
$ yum -y install ntp
$ vim /etc/ntp.conf # 修改配置文件
# 找到(17行左右):
#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
# 改为(网段是你自己的网段,表示允许哪个网段的客户端来同步时间):
restrict 192.168.20.0 mask 255.255.255.0 nomodify notrap
# 找到
server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst
# 将其注释掉,表示不使用互联网上的时间同步服务器
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
# 末尾追加
server 127.127.1.0
fudge 127.127.1.0 stratum 5
# 在上级时钟源失效时,NTP会使用127.127.1.0的本地时钟,将local时间作为ntp服务器时间提供给ntp客户端。
# NTP把本地主机的时钟也看作外部时钟源来处理,分配的地址是127.127.1.0
# 让硬件时间和系统时间一起同步
$ echo 'SYNC_HWCLOCK=yes' >> /etc/sysconfig/ntpd
# 重启ntp服务器生效
$ systemctl restart ntpd && systemctl enable ntpd
# 配置其他客户端定时同步时间(哪些机器要同步上面时间服务器的时间,就进行以下配置)
$ yum -y install ntp
$ crontab -e # 写入以下定时任务
*/5 * * * * /usr/sbin/ntpdate 192.168.20.2 &> /dev/null
安装MySQL
需要参考:Mysql 8. 0安装,在三个节点上都安装MySQL服务。
安装完毕后,需要保证可以登录到节点上。
$ mysql -uroot -p123.com
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
安装MGR插件
所有节点均需执行此安装插件的操作。
# 确认插件是否存在
$ ll /data/mysql-3306/lib/plugin/group_replication.so
-rwxr-xr-x 1 mysql mysql 24953048 7月 1 2021 /data/mysql-3306/lib/plugin/group_replication.so
# 进入mysql数据库进行安装
$ mysql -uroot -p123.com
mysql> install PLUGIN group_replication SONAME 'group_replication.so';
# 查看安装的插件
mysql> select * from mysql.plugin;
+-------------------+----------------------+
| name | dl |
+-------------------+----------------------+
| group_replication | group_replication.so |
+-------------------+----------------------+
# 查看MGR相关的参数
mysql> show variables like 'group%';
+-----------------------------------------------------+-------------------------------+
| Variable_name | Value |
+-----------------------------------------------------+-------------------------------+
| group_concat_max_len | 1024 |
| group_replication_advertise_recovery_endpoints | DEFAULT |
| group_replication_allow_local_lower_version_join | OFF |
| group_replication_auto_increment_increment | 7 |
| group_replication_autorejoin_tries | 3 |
| group_replication_bootstrap_group | OFF |
| group_replication_clone_threshold | 9223372036854775807 |
| group_replication_communication_debug_options | GCS_DEBUG_NONE |
| group_replication_communication_max_message_size | 10485760 |
| group_replication_components_stop_timeout | 31536000 |
| group_replication_compression_threshold | 1000000 |
| group_replication_consistency | EVENTUAL |
| 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_hold_percent | 10 |
| group_replication_flow_control_max_quota | 0 |
| group_replication_flow_control_member_quota_percent | 0 |
| group_replication_flow_control_min_quota | 0 |
| group_replication_flow_control_min_recovery_quota | 0 |
| group_replication_flow_control_mode | QUOTA |
| group_replication_flow_control_period | 1 |
| group_replication_flow_control_release_percent | 50 |
| group_replication_force_members | |
| group_replication_group_name | |
| group_replication_group_seeds | |
| group_replication_gtid_assignment_block_size | 1000000 |
| group_replication_ip_allowlist | AUTOMATIC |
| group_replication_ip_whitelist | AUTOMATIC |
| group_replication_local_address | |
| group_replication_member_expel_timeout | 5 |
| group_replication_member_weight | 50 |
| group_replication_message_cache_size | 1073741824 |
| group_replication_poll_spin_loops | 0 |
| group_replication_recovery_complete_at | TRANSACTIONS_APPLIED |
| group_replication_recovery_compression_algorithms | uncompressed |
| group_replication_recovery_get_public_key | OFF |
| group_replication_recovery_public_key_path | |
| group_replication_recovery_reconnect_interval | 60 |
| group_replication_recovery_retry_count | 10 |
| group_replication_recovery_ssl_ca | |
| group_replication_recovery_ssl_capath | |
| group_replication_recovery_ssl_cert | |
| group_replication_recovery_ssl_cipher | |
| group_replication_recovery_ssl_crl | |
| group_replication_recovery_ssl_crlpath | |
| group_replication_recovery_ssl_key | |
| group_replication_recovery_ssl_verify_server_cert | OFF |
| group_replication_recovery_tls_ciphersuites | |
| group_replication_recovery_tls_version | TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 |
| group_replication_recovery_use_ssl | OFF |
| group_replication_recovery_zstd_compression_level | 3 |
| group_replication_single_primary_mode | ON |
| group_replication_ssl_mode | DISABLED |
| group_replication_start_on_boot | ON |
| group_replication_tls_source | MYSQL_MAIN |
| group_replication_transaction_size_limit | 150000000 |
| group_replication_unreachable_majority_timeout | 0 |
| group_replication_view_change_uuid | AUTOMATIC |
+-----------------------------------------------------+-------------------------------+
60 rows in set (0.13 sec)
配置MGR环境
修改centos-20-2节点配置文件
$ cat /etc/my.cnf # 完整配置文件如下
[mysqld]
basedir=/data/mysql-3306
datadir=/data/mysql-3306/data
pid-file=/data/mysql-3306/data/mysqld.pid
log-error=/data/mysql-3306/data/mysql.err
socket=/tmp/mysql.sock
################################ 下面是为了配置MGR集群而新增的配置 ################################
# 开启GTID,必须开启
gtid_mode=on
# 强制GTID的一致性
enforce-gtid-consistency=on
# binlog格式,MGR要求必须是ROW,不过就算不是MGR,也最好用row
binlog_format=row
# server-id必须是唯一的
server-id = 202
# MGR使用乐观锁,所以官网建议隔离级别是RC,减少锁粒度
transaction_isolation = READ-COMMITTED
# 因为集群会在故障恢复时互相检查binlog的数据,
# 所以需要记录下集群内其他服务器发过来已经执行过的binlog,按GTID来区分是否执行过.
log-slave-updates=1
# binlog校验规则,5.6之后的高版本是CRC32,低版本都是NONE,但是MGR要求使用NONE
binlog_checksum=NONE
# 基于安全的考虑,MGR集群要求复制模式要改成slave记录记录到表中,不然就报错
master_info_repository=TABLE
# 同上配套
relay_log_info_repository=TABLE
# 记录事务的算法,官网建议设置该参数使用 XXHASH64 算法
transaction_write_set_extraction = XXHASH64
# 相当于此GROUP的名字,是UUID值,主要是用来定义一个MGR集群的统一UUID
# 参加MGR集群的节点必须配置相同的UUID值,可用uuidgen命令来生成一个新的,
loose-group_replication_group_name = '25f94c95-31de-446a-9646-ba6fdb1b7cd1'
# IP地址白名单,默认只添加127.0.0.1,不会允许来自外部主机的连接,按需安全设置
# 建议使用group_replication_ip_allowlist参数代替loose-group_replication_ip_whitelist
#(在后面配置会报warning,但不会影响功能,group_replication_ip_allowlist参数未经验证哦)
loose-group_replication_ip_whitelist = '127.0.0.1/8,192.168.20.2,192.168.20.3,192.168.20.4'
# 是否随服务器启动而自动启动组复制,不建议直接启动,怕故障恢复时有扰乱数据准确性的特殊情况
loose-group_replication_start_on_boot = OFF
# 本地MGR的IP地址和端口,host:port,是MGR的端口,不是数据库的端口
loose-group_replication_local_address = '192.168.20.2:33061'
# 需要接受本MGR实例控制的服务器IP地址和端口,是MGR的端口,不是数据库的端口
loose-group_replication_group_seeds = '192.168.20.2:33061,192.168.20.3:33061,192.168.20.4:33061'
# 开启引导模式,添加组成员,用于第一次搭建MGR或重建MGR的时候使用,只需要在集群内的其中一台开启
# 在配置文件中统一关闭,等重启后,进入mysql动态开启即可,待引导成功后,还需将其关闭
loose-group_replication_bootstrap_group = OFF
# 是否启动单主模式,如果启动,则本实例是主库,提供读写,其他实例仅提供读,如果为off就是多主模式了
loose-group_replication_single_primary_mode = off
# 多主模式下,强制检查每一个实例是否允许该操作,如果不是多主,可以关闭
loose-group_replication_enforce_update_everywhere_checks = on
# 安全相关配置
group_replication_recovery_get_public_key = ON
################################ MGR集群相关配置至此结束 ################################
[client]
socket=/tmp/mysql.sock
这里捡几个重要参数说一下:
- group_replication_group_name:这个是集群的UUID值,参与集群的所有节点,此值必须一致。在linux系统下可以用uuidgen来生成一个新的UUID
- group_replication_ip_whitelist:关于IP白名单来说,本来是安全设置,如果全内网涵盖是不太适合的,这样设置只是为了方便,这个参数可以set global动态修改,还是比较方便的;
- group_replication_start_on_boot:不建议随系统启动的原因有两个,第一个就是怕故障恢复时的极端情况下影响数据准确性,第二个就是怕一些添加或移除节点的操作被这个参数影响到;
- group_replication_local_address:特别注意的是这个端口并不是数据库服务端口,是MGR的服务端口,而且要保证这个端口没有被使用,是MGR互相通信使用的端口.
- group_replication_group_seeds:接受本group控制的IP地址和端口号,这个端口也是MGR的服务端口,可以用set global动态修改,用以添加和移动节点.;
- group_replication_bootstrap_group:需要特别注意,引导的服务器只需要一台,所以集群内其他服务器都不需要开启这个参数,默认off就好了,有需要再set global来开启就足够了;
- group_replication_single_primary_mode:取决于想用的是多主模式还是单主模式,如果是单主模式,就类似于半同步复制,但是比半同步要求更高,因为需要集群内过半数的服务器写入成功后,主库才会返回写入成功,数据一致性也更高,通常金融服务也更推荐这种使用方法.如果是多主模式,看上去性能更高,但是事务冲突的几率也更高,虽然MGR内部有先到先得原则,但是这些还是不能忽略,对于高并发环境,更加可能是致命的,所以一般多主模式也是建议分开来使用,一个地址链接一个库,从逻辑操作上区分开来,避免冲突的可能。
- group_replication_enforce_update_everywhere_checks: 如果是单主模式,因为不存在多主同时操作的可能,这个强制检查是可以关闭,因为已经不存在这样的操作,多主是必须要开的,不开的话数据就可能出现错乱了。
发送修改后的配置文件至其他两个节点
$ for i in 3 4 ;do scp /etc/my.cnf root@192.168.20.$i:/etc/ ;done
修改centos-20-3节点配置文件
$ sed -i 's#loose-group_replication_local_address.*#loose-group_replication_local_address = '192.168.20.3:33061'#g' /etc/my.cnf
sed -i 's#server-id =.*#server-id = 203#g' /etc/my.cnf
修改centos-20-4节点配置文件
$ sed -i 's#loose-group_replication_local_address.*#loose-group_replication_local_address = '192.168.20.4:33061'#g' /etc/my.cnf
sed -i 's#server-id =.*#server-id = 204#g' /etc/my.cnf
重启节点以便配置生效
# 在所有节点执行
$ systemctl restart mysqld
启动MGR集群
如上面说的,启动MGR是要注意顺序的,因为需要有其中一台数据库做引导,其他数据库才可以顺利加入进来。如果是单主模式,那么主库就一定要先启动并做引导,不然就不是主了。
当出现异常时,应该要去查看mysql报错文件mysql.err,一般都有相应的error日志提示。
好了,转回正题,现在假设用192.168.20.2
这台服务器做引导,先登进本地mysql服务端:
# 启动引导,注意,只有这套开启引导,其他两台都请忽略这一步
mysql> SET GLOBAL group_replication_bootstrap_group=ON;
# 创建一个用户来做同步的用户,并授权,所有集群内的服务器都需要做
mysql> create user 'repl'@'%' identified by '123.com';
mysql> grant REPLICATION SLAVE on *.* to 'repl'@'%' with grant option;
# 清空所有旧的GTID信息,避免冲突
mysql> reset master;
# 创建同步规则认证信息,就是刚才授权的那个用户,和一般的主从规则写法不太一样
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='123.com' FOR CHANNEL 'group_replication_recovery';
# 启动MGR
mysql> start group_replication;
# 查看是否启动成功,看到online就是成功了
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
# 这个时候,就可以先关闭引导了
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
然后,就到另外两台服务器192.168.20.3
和192.168.20.4
了,也是要登进本地mysql服务端(20.3和20.4两个节点上都要进行下面的配置):
# 不需要启动引导了,下面大致是类似的
# 用户授权还是要做的
mysql> create user 'repl'@'%' identified by '123.com';
mysql> grant REPLICATION SLAVE on *.* to 'repl'@'%' with grant option;
# 清空所有旧的GTID信息,避免冲突
mysql> reset master;
# 创建同步规则认证信息,就是刚才授权的那个用户,和一般的主从规则写法不太一样
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='123.com' FOR CHANNEL 'group_replication_recovery';
#启动MGR
mysql> start group_replication;
# 查看是否启动成功,看到online就是成功了
mysql> SELECT * FROM performance_schema.replication_group_members;
如此类推,在192.168.20.4
上就应该是下面这样了:
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)
看到MEMBER_STATE
全部都是online就是成功连接上了,不过如果出现故障,是会被剔除出集群的并且在本机上会显示error,这个时候就需要去看本机的mysql报错文件mysql.err了。
需要注意的是,现在是多主模式,MEMBER_ROLE
里显示的都是PRIMARY
,如果是单主模式,就会只显示一个PRIMARY
,其他是SECONDARY
了。
MGR集群运维相关
全集群重启后如何恢复
当三个节点都重启过后,查看组复制状态如下:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | | | NULL | OFFLINE | | |
+---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+
1 row in set (0.00 sec)
好,现在需要在其中一个主节点执行如下指令,以便重新引导集群:
# 开启引导模式
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, 1 warning (2.21 sec)
# 查看组成员状态,本节点是否为 ONLINE
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
1 row in set (0.00 sec)
# 关闭引导模式
mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
在剩下其他节点直接开启组复制:
# 开启组复制
mysql> start group_replication;
Query OK, 0 rows affected, 1 warning (2.62 sec)
最后任意一个节点查看组复制状态:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.35 sec)
至此,MGR集群恢复成功。
MGR三节点集群故障两个节点,如何恢复
停掉两个mysql节点,模拟故障。
分别停止centos-20-2
和centos-20-4
两个节点,如下:
# 只将3306数据库的进程杀掉,守护进程不杀
$ ps -ef | grep mysql | grep -v grep | awk '{print $2}' | tail -1 | xargs kill -9
然后在centos-20-3
节点查看集群状态如下:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | UNREACHABLE | PRIMARY | 8.0.26 |
| group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | UNREACHABLE | PRIMARY | 8.0.26 |
| group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)
可以看到停掉进程的那几个节点状态都为:UNREACHABLE
。
这里说下
MEMBER_STATE
的不同值都是什么意思:
- offline:gr插件未启动;
- recovering:复制加入集群之前产生的数据;
- online:完成后,可对外服务;
- error:节点出现错误,gr无法正常运行;
- unreachable:无法与其他成员通信,网络问题或其他成员非正常退出;
由于此时,三节点集群宕了两个,也就是半数节点都宕了,也就导致集群现在无法写入,集群无法对外服务了。如下:
# 在存活的节点上写入数据会hang住
mysql> insert into test_info values(2,19,'lisi');
# 新开一个窗口,登录到数据库,查看innodb的事务,如下:
mysql> select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 3442
trx_state: RUNNING
trx_started: 2022-01-03 16:10:58
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 2
trx_mysql_thread_id: 8
trx_query: insert into test_info values(2,19,'lisi')
trx_operation_state: NULL
trx_tables_in_use: 1
trx_tables_locked: 1
trx_lock_structs: 1
trx_lock_memory_bytes: 1128
trx_rows_locked: 0
trx_rows_modified: 1
trx_concurrency_tickets: 0
trx_isolation_level: READ COMMITTED
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
trx_schedule_weight: NULL
1 row in set (0.00 sec)
# 进程列表
mysql> show processlist;
+----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 5153 | Waiting on empty queue | NULL |
| 8 | root | localhost | ljz | Query | 300 | waiting for handler commit | insert into test_info values(2,19,'lisi') |
| 10 | system user | | NULL | Connect | 4120 | waiting for handler commit | Group replication applier module |
| 13 | system user | | NULL | Query | 4120 | Replica has read all relay log; waiting for more updates | NULL |
| 31 | root | localhost | NULL | Query | 0 | init | show processlist |
+----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
5 rows in set (0.00 sec)
# kill掉hang住的进程
mysql> kill 8;
Query OK, 0 rows affected (0.00 sec)
# 原来hang住的session会报错如下:
mysql> insert into test_info values(2,19,'lisi');
ERROR 2013 (HY000): Lost connection to MySQL server during query
# 再次查看进程列表
mysql> show processlist;
+----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 5707 | Waiting on empty queue | NULL |
| 8 | root | localhost | ljz | Killed | 854 | waiting for handler commit | insert into test_info values(2,19,'lisi') |
| 10 | system user | | NULL | Connect | 4674 | waiting for handler commit | Group replication applier module |
| 13 | system user | | NULL | Query | 4674 | Replica has read all relay log; waiting for more updates | NULL |
| 31 | root | localhost | NULL | Query | 0 | init | show processlist |
| 32 | root | localhost | ljz | Sleep | 184 | | NULL |
+----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
6 rows in set (0.00 sec)
kill这个hang住的session竟然没有成功,只是显示killed,这个为什么一直显示killed呢,先放着。
看master的错误日志,如下:
2022-01-03T08:03:07.141329Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication reported: 'Member with address centos-20-2:3306 has become unreachable.'
2022-01-03T08:03:16.205884Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication reported: 'Member with address centos-20-4:3306 has become unreachable.'
2022-01-03T08:03:16.205996Z 0 [ERROR] [MY-011495] [Repl] Plugin group_replication reported: 'This server is not able to reach a majority of members in the group. This server will now block all updates. The server will remain blocked until contact with the majority is restored. It is possible to use group_replication_force_members to force a new group membership.'
最后一句啥意思懂吧?
此服务器无法访问组中的大多数成员。
此服务器现在将阻止所有更新。
在恢复与大多数成员的通信之前,服务器将保持被阻塞状态。
可以使用group_replication_force_members参数强制更新组成员
故障恢复
言下之意,将活着的节点,重新组成新集群。那就来试一下:
# 设置为本机的IP+MGR端口
mysql> set global group_replication_force_members = "192.168.20.3:33061";
Query OK, 0 rows affected (6.80 sec)
# 查看MGR状态
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
1 row in set (0.00 sec)
# 插入数据测试
mysql> insert into test_info values(3,19,'lisi');
Query OK, 1 row affected (0.00 sec)
mysql> select * from test_info;
+----+-----+--------+
| id | age | name |
+----+-----+--------+
| 1 | 18 | 张三 |
| 2 | 19 | lisi | # 刚才hang住的那一条记录也被插入进来了
| 3 | 19 | lisi |
+----+-----+--------+
3 rows in set (0.00 sec)
我们服务现在已经恢复了,后续把节点再加进去即可。
需要注意的是:
- 加节点,注意每个节点的模式一致,单主还是多主,可以通过
show variables like '%group_replication_single_primary_mode%';
来确认,如果为OFF
,则表明为多主模式,如果为ON
,则为单主;- 事后最好把group_replication_force_members重新置空,不处理也问题不大;
- 直接在不可用集群中加节点是加不了的,必须先恢复集群可用才能加节点;
好,我们现在把其他节点都加入到集群中,如下:
# 先将目前的主节点centos-20-3的group_replication_force_members值设置为空
mysql> set global group_replication_force_members = "";
Query OK, 0 rows affected (0.00 sec)
修复故障节点,然后开始组复制:
# 我这边直接重启刚才的故障节点即可修复
$ systemctl restart mysqld
# 登录刚恢复的节点,开启组复制
$ mysql -uroot -p123.com
mysql> start group_replication;
最后在任意一个节点,查看组复制状态如下:
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.01 sec)
MGR监控
这里说是监控,其实就是一些集群中常用的运维用的元数据信息吧
查看节点状态
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
| group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
3 rows in set (0.01 sec)
说下member_state字段吧!
值 | 含义 |
---|---|
offline | gr插件未启动 |
recovering | 复制加入集群之前产生的数据 |
online | 完成后,可对外服务 |
error | 节点出现错误,gr无法正常运行 |
unreachable | 无法与其他成员通信,网络问题或其他成员非正常退出 |
查看成员详细信息
这里注释一些必要字段说明。
mysql> select * from performance_schema.replication_group_member_stats limit 1\G
*************************** 1. row ***************************
CHANNEL_NAME: group_replication_applier
VIEW_ID: 15915014697349018:6 组视图id
MEMBER_ID: a50df330-a4b0-11ea-bfd3-fa163ed6ef91
COUNT_TRANSACTIONS_IN_QUEUE: 0 队列中等待做全局事务认证的事务数量
COUNT_TRANSACTIONS_CHECKED: 2 做了全局事务认证的事务总数量,从加入组开始
COUNT_CONFLICTS_DETECTED: 0 全局事务认证时,有冲突的事务总数量
COUNT_TRANSACTIONS_ROWS_VALIDATING: 0 冲突检测的记录总行数
TRANSACTIONS_COMMITTED_ALL_MEMBERS: 745c2bc6-9fe4-11ea-8c89-fa163e98606f:1-69:1000003-1000005:2000005-2000006 所有事务的gtid集合,相当于gtid_executed交集,非实时,隔段时间更新一次
LAST_CONFLICT_FREE_TRANSACTION: 745c2bc6-9fe4-11ea-8c89-fa163e98606f:67 最后一个没有冲突的事务gtid
COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE: 0 当前节点从gr中接收到的正在等待被应用的事务数量
COUNT_TRANSACTIONS_REMOTE_APPLIED: 5 当前节点从gr中接收的已经应用的事务数量
COUNT_TRANSACTIONS_LOCAL_PROPOSED: 2 当前节点产生并发送给gr的事务数量
COUNT_TRANSACTIONS_LOCAL_ROLLBACK: 0 当前节点产生并被gr回滚的事务数量
1 row in set (0.00 sec)
其他表
- replication_connection_status:新节点加入集群,先通过异步复制拉取加入组之前产生的数据,通过这个表监控这个过程;
- replication_applier_status:group_replication_applier通道来执行binlog event,通过这个表监控这个过程;
- threads:该表监控gr组件的线程;
注:上述提到的表,都在performance_schema库中。