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集群无法构建成功。

配置主机名解析

  1. cat >> /etc/hosts << EOF
  2. 192.168.20.2 centos-20-2
  3. 192.168.20.3 centos-20-3
  4. 192.168.20.4 centos-20-4
  5. EOF

修改系统限制

  1. $ mv /etc/security/limits.conf{,.bak}
  2. cat > /etc/security/limits.conf << EOF
  3. * - nofile 655360
  4. * - memlock unlimited
  5. * - stack 655360
  6. * - nproc unlimited
  7. EOF
  8. cat > /etc/sysctl.conf << EOF
  9. kernel.sysrq = 0
  10. kernel.core_uses_pid = 1
  11. fs.file-max=655360
  12. kernel.msgmnb = 65536
  13. kernel.msgmax = 65536
  14. kernel.shmmax = 68719476736
  15. kernel.shmall = 4294967296
  16. kernel.pid_max = 655360
  17. net.ipv4.tcp_tw_reuse = 1
  18. net.ipv4.tcp_tw_recycle = 0
  19. net.ipv4.tcp_max_tw_buckets = 10000
  20. net.ipv4.tcp_fin_timeout = 30
  21. net.ipv4.tcp_timestamps = 0
  22. net.ipv4.tcp_sack = 1
  23. net.ipv4.tcp_window_scaling = 1
  24. net.ipv4.tcp_ecn = 0
  25. net.ipv4.tcp_keepalive_time = 600
  26. net.ipv4.tcp_keepalive_intvl = 30
  27. net.ipv4.tcp_keepalive_probes = 3
  28. net.ipv4.tcp_max_orphans = 655360
  29. net.ipv4.tcp_max_syn_backlog = 262144
  30. net.ipv4.tcp_mem = 65536 131072 262144
  31. net.ipv4.udp_mem = 65536 131072 262144
  32. net.ipv4.tcp_rmem = 4096 87380 16777216
  33. net.ipv4.tcp_wmem = 4096 16384 16777216
  34. net.ipv4.ip_local_port_range = 1024 65535
  35. net.ipv4.route.gc_timeout = 100
  36. # 禁止icmp重定向报文
  37. net.ipv4.conf.all.accept_redirects = 0
  38. # 禁止icmp源路由
  39. net.ipv4.conf.all.accept_source_route = 0
  40. net.core.somaxconn = 65535
  41. net.core.rmem_default = 8388608
  42. net.core.wmem_default = 8388608
  43. net.core.rmem_max = 16777216
  44. net.core.wmem_max = 16777216
  45. net.core.netdev_max_backlog = 262144
  46. vm.swappiness = 10
  47. vm.overcommit_memory = 1
  48. vm.max_map_count = 262144
  49. EOF
  50. sysctl -p

配置ntp时间同步

任意一台节点配置时间服务器,其他节点制定定时任务即可。

  1. $ yum -y install ntp
  2. $ vim /etc/ntp.conf # 修改配置文件
  3. # 找到(17行左右):
  4. #restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
  5. # 改为(网段是你自己的网段,表示允许哪个网段的客户端来同步时间):
  6. restrict 192.168.20.0 mask 255.255.255.0 nomodify notrap
  7. # 找到
  8. server 0.centos.pool.ntp.org iburst
  9. server 1.centos.pool.ntp.org iburst
  10. server 2.centos.pool.ntp.org iburst
  11. server 3.centos.pool.ntp.org iburst
  12. # 将其注释掉,表示不使用互联网上的时间同步服务器
  13. #server 0.centos.pool.ntp.org iburst
  14. #server 1.centos.pool.ntp.org iburst
  15. #server 2.centos.pool.ntp.org iburst
  16. #server 3.centos.pool.ntp.org iburst
  17. # 末尾追加
  18. server 127.127.1.0
  19. fudge 127.127.1.0 stratum 5
  20. # 在上级时钟源失效时,NTP会使用127.127.1.0的本地时钟,将local时间作为ntp服务器时间提供给ntp客户端。
  21. # NTP把本地主机的时钟也看作外部时钟源来处理,分配的地址是127.127.1.0
  22. # 让硬件时间和系统时间一起同步
  23. $ echo 'SYNC_HWCLOCK=yes' >> /etc/sysconfig/ntpd
  24. # 重启ntp服务器生效
  25. $ systemctl restart ntpd && systemctl enable ntpd
  26. # 配置其他客户端定时同步时间(哪些机器要同步上面时间服务器的时间,就进行以下配置)
  27. $ yum -y install ntp
  28. $ crontab -e # 写入以下定时任务
  29. */5 * * * * /usr/sbin/ntpdate 192.168.20.2 &> /dev/null

安装MySQL

需要参考:Mysql 8. 0安装,在三个节点上都安装MySQL服务。

安装完毕后,需要保证可以登录到节点上。

  1. $ mysql -uroot -p123.com
  2. mysql> select version();
  3. +-----------+
  4. | version() |
  5. +-----------+
  6. | 8.0.26 |
  7. +-----------+

安装MGR插件

所有节点均需执行此安装插件的操作。

  1. # 确认插件是否存在
  2. $ ll /data/mysql-3306/lib/plugin/group_replication.so
  3. -rwxr-xr-x 1 mysql mysql 24953048 7 1 2021 /data/mysql-3306/lib/plugin/group_replication.so
  4. # 进入mysql数据库进行安装
  5. $ mysql -uroot -p123.com
  6. mysql> install PLUGIN group_replication SONAME 'group_replication.so';
  7. # 查看安装的插件
  8. mysql> select * from mysql.plugin;
  9. +-------------------+----------------------+
  10. | name | dl |
  11. +-------------------+----------------------+
  12. | group_replication | group_replication.so |
  13. +-------------------+----------------------+
  14. # 查看MGR相关的参数
  15. mysql> show variables like 'group%';
  16. +-----------------------------------------------------+-------------------------------+
  17. | Variable_name | Value |
  18. +-----------------------------------------------------+-------------------------------+
  19. | group_concat_max_len | 1024 |
  20. | group_replication_advertise_recovery_endpoints | DEFAULT |
  21. | group_replication_allow_local_lower_version_join | OFF |
  22. | group_replication_auto_increment_increment | 7 |
  23. | group_replication_autorejoin_tries | 3 |
  24. | group_replication_bootstrap_group | OFF |
  25. | group_replication_clone_threshold | 9223372036854775807 |
  26. | group_replication_communication_debug_options | GCS_DEBUG_NONE |
  27. | group_replication_communication_max_message_size | 10485760 |
  28. | group_replication_components_stop_timeout | 31536000 |
  29. | group_replication_compression_threshold | 1000000 |
  30. | group_replication_consistency | EVENTUAL |
  31. | group_replication_enforce_update_everywhere_checks | OFF |
  32. | group_replication_exit_state_action | READ_ONLY |
  33. | group_replication_flow_control_applier_threshold | 25000 |
  34. | group_replication_flow_control_certifier_threshold | 25000 |
  35. | group_replication_flow_control_hold_percent | 10 |
  36. | group_replication_flow_control_max_quota | 0 |
  37. | group_replication_flow_control_member_quota_percent | 0 |
  38. | group_replication_flow_control_min_quota | 0 |
  39. | group_replication_flow_control_min_recovery_quota | 0 |
  40. | group_replication_flow_control_mode | QUOTA |
  41. | group_replication_flow_control_period | 1 |
  42. | group_replication_flow_control_release_percent | 50 |
  43. | group_replication_force_members | |
  44. | group_replication_group_name | |
  45. | group_replication_group_seeds | |
  46. | group_replication_gtid_assignment_block_size | 1000000 |
  47. | group_replication_ip_allowlist | AUTOMATIC |
  48. | group_replication_ip_whitelist | AUTOMATIC |
  49. | group_replication_local_address | |
  50. | group_replication_member_expel_timeout | 5 |
  51. | group_replication_member_weight | 50 |
  52. | group_replication_message_cache_size | 1073741824 |
  53. | group_replication_poll_spin_loops | 0 |
  54. | group_replication_recovery_complete_at | TRANSACTIONS_APPLIED |
  55. | group_replication_recovery_compression_algorithms | uncompressed |
  56. | group_replication_recovery_get_public_key | OFF |
  57. | group_replication_recovery_public_key_path | |
  58. | group_replication_recovery_reconnect_interval | 60 |
  59. | group_replication_recovery_retry_count | 10 |
  60. | group_replication_recovery_ssl_ca | |
  61. | group_replication_recovery_ssl_capath | |
  62. | group_replication_recovery_ssl_cert | |
  63. | group_replication_recovery_ssl_cipher | |
  64. | group_replication_recovery_ssl_crl | |
  65. | group_replication_recovery_ssl_crlpath | |
  66. | group_replication_recovery_ssl_key | |
  67. | group_replication_recovery_ssl_verify_server_cert | OFF |
  68. | group_replication_recovery_tls_ciphersuites | |
  69. | group_replication_recovery_tls_version | TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 |
  70. | group_replication_recovery_use_ssl | OFF |
  71. | group_replication_recovery_zstd_compression_level | 3 |
  72. | group_replication_single_primary_mode | ON |
  73. | group_replication_ssl_mode | DISABLED |
  74. | group_replication_start_on_boot | ON |
  75. | group_replication_tls_source | MYSQL_MAIN |
  76. | group_replication_transaction_size_limit | 150000000 |
  77. | group_replication_unreachable_majority_timeout | 0 |
  78. | group_replication_view_change_uuid | AUTOMATIC |
  79. +-----------------------------------------------------+-------------------------------+
  80. 60 rows in set (0.13 sec)

配置MGR环境

修改centos-20-2节点配置文件
  1. $ cat /etc/my.cnf # 完整配置文件如下
  2. [mysqld]
  3. basedir=/data/mysql-3306
  4. datadir=/data/mysql-3306/data
  5. pid-file=/data/mysql-3306/data/mysqld.pid
  6. log-error=/data/mysql-3306/data/mysql.err
  7. socket=/tmp/mysql.sock
  8. ################################ 下面是为了配置MGR集群而新增的配置 ################################
  9. # 开启GTID,必须开启
  10. gtid_mode=on
  11. # 强制GTID的一致性
  12. enforce-gtid-consistency=on
  13. # binlog格式,MGR要求必须是ROW,不过就算不是MGR,也最好用row
  14. binlog_format=row
  15. # server-id必须是唯一的
  16. server-id = 202
  17. # MGR使用乐观锁,所以官网建议隔离级别是RC,减少锁粒度
  18. transaction_isolation = READ-COMMITTED
  19. # 因为集群会在故障恢复时互相检查binlog的数据,
  20. # 所以需要记录下集群内其他服务器发过来已经执行过的binlog,按GTID来区分是否执行过.
  21. log-slave-updates=1
  22. # binlog校验规则,5.6之后的高版本是CRC32,低版本都是NONE,但是MGR要求使用NONE
  23. binlog_checksum=NONE
  24. # 基于安全的考虑,MGR集群要求复制模式要改成slave记录记录到表中,不然就报错
  25. master_info_repository=TABLE
  26. # 同上配套
  27. relay_log_info_repository=TABLE
  28. # 记录事务的算法,官网建议设置该参数使用 XXHASH64 算法
  29. transaction_write_set_extraction = XXHASH64
  30. # 相当于此GROUP的名字,是UUID值,主要是用来定义一个MGR集群的统一UUID
  31. # 参加MGR集群的节点必须配置相同的UUID值,可用uuidgen命令来生成一个新的,
  32. loose-group_replication_group_name = '25f94c95-31de-446a-9646-ba6fdb1b7cd1'
  33. # IP地址白名单,默认只添加127.0.0.1,不会允许来自外部主机的连接,按需安全设置
  34. # 建议使用group_replication_ip_allowlist参数代替loose-group_replication_ip_whitelist
  35. #(在后面配置会报warning,但不会影响功能,group_replication_ip_allowlist参数未经验证哦)
  36. loose-group_replication_ip_whitelist = '127.0.0.1/8,192.168.20.2,192.168.20.3,192.168.20.4'
  37. # 是否随服务器启动而自动启动组复制,不建议直接启动,怕故障恢复时有扰乱数据准确性的特殊情况
  38. loose-group_replication_start_on_boot = OFF
  39. # 本地MGR的IP地址和端口,host:port,是MGR的端口,不是数据库的端口
  40. loose-group_replication_local_address = '192.168.20.2:33061'
  41. # 需要接受本MGR实例控制的服务器IP地址和端口,是MGR的端口,不是数据库的端口
  42. loose-group_replication_group_seeds = '192.168.20.2:33061,192.168.20.3:33061,192.168.20.4:33061'
  43. # 开启引导模式,添加组成员,用于第一次搭建MGR或重建MGR的时候使用,只需要在集群内的其中一台开启
  44. # 在配置文件中统一关闭,等重启后,进入mysql动态开启即可,待引导成功后,还需将其关闭
  45. loose-group_replication_bootstrap_group = OFF
  46. # 是否启动单主模式,如果启动,则本实例是主库,提供读写,其他实例仅提供读,如果为off就是多主模式了
  47. loose-group_replication_single_primary_mode = off
  48. # 多主模式下,强制检查每一个实例是否允许该操作,如果不是多主,可以关闭
  49. loose-group_replication_enforce_update_everywhere_checks = on
  50. # 安全相关配置
  51. group_replication_recovery_get_public_key = ON
  52. ################################ MGR集群相关配置至此结束 ################################
  53. [client]
  54. 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: 如果是单主模式,因为不存在多主同时操作的可能,这个强制检查是可以关闭,因为已经不存在这样的操作,多主是必须要开的,不开的话数据就可能出现错乱了。

发送修改后的配置文件至其他两个节点
  1. $ for i in 3 4 ;do scp /etc/my.cnf root@192.168.20.$i:/etc/ ;done

修改centos-20-3节点配置文件
  1. $ sed -i 's#loose-group_replication_local_address.*#loose-group_replication_local_address = '192.168.20.3:33061'#g' /etc/my.cnf
  2. sed -i 's#server-id =.*#server-id = 203#g' /etc/my.cnf

修改centos-20-4节点配置文件
  1. $ sed -i 's#loose-group_replication_local_address.*#loose-group_replication_local_address = '192.168.20.4:33061'#g' /etc/my.cnf
  2. sed -i 's#server-id =.*#server-id = 204#g' /etc/my.cnf

重启节点以便配置生效
  1. # 在所有节点执行
  2. $ systemctl restart mysqld

启动MGR集群

如上面说的,启动MGR是要注意顺序的,因为需要有其中一台数据库做引导,其他数据库才可以顺利加入进来。如果是单主模式,那么主库就一定要先启动并做引导,不然就不是主了。

当出现异常时,应该要去查看mysql报错文件mysql.err,一般都有相应的error日志提示。

好了,转回正题,现在假设用192.168.20.2这台服务器做引导,先登进本地mysql服务端:

  1. # 启动引导,注意,只有这套开启引导,其他两台都请忽略这一步
  2. mysql> SET GLOBAL group_replication_bootstrap_group=ON;
  3. # 创建一个用户来做同步的用户,并授权,所有集群内的服务器都需要做
  4. mysql> create user 'repl'@'%' identified by '123.com';
  5. mysql> grant REPLICATION SLAVE on *.* to 'repl'@'%' with grant option;
  6. # 清空所有旧的GTID信息,避免冲突
  7. mysql> reset master;
  8. # 创建同步规则认证信息,就是刚才授权的那个用户,和一般的主从规则写法不太一样
  9. mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='123.com' FOR CHANNEL 'group_replication_recovery';
  10. # 启动MGR
  11. mysql> start group_replication;
  12. # 查看是否启动成功,看到online就是成功了
  13. mysql> SELECT * FROM performance_schema.replication_group_members;
  14. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  15. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  16. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  17. | group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  18. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  19. # 这个时候,就可以先关闭引导了
  20. mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

然后,就到另外两台服务器192.168.20.3192.168.20.4了,也是要登进本地mysql服务端(20.3和20.4两个节点上都要进行下面的配置):

  1. # 不需要启动引导了,下面大致是类似的
  2. # 用户授权还是要做的
  3. mysql> create user 'repl'@'%' identified by '123.com';
  4. mysql> grant REPLICATION SLAVE on *.* to 'repl'@'%' with grant option;
  5. # 清空所有旧的GTID信息,避免冲突
  6. mysql> reset master;
  7. # 创建同步规则认证信息,就是刚才授权的那个用户,和一般的主从规则写法不太一样
  8. mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='123.com' FOR CHANNEL 'group_replication_recovery';
  9. #启动MGR
  10. mysql> start group_replication;
  11. # 查看是否启动成功,看到online就是成功了
  12. mysql> SELECT * FROM performance_schema.replication_group_members;

如此类推,在192.168.20.4上就应该是下面这样了:

  1. mysql> SELECT * FROM performance_schema.replication_group_members;
  2. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  3. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  4. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  5. | group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  6. | group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  7. | group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  8. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  9. 3 rows in set (0.00 sec)

看到MEMBER_STATE全部都是online就是成功连接上了,不过如果出现故障,是会被剔除出集群的并且在本机上会显示error,这个时候就需要去看本机的mysql报错文件mysql.err了。

需要注意的是,现在是多主模式,MEMBER_ROLE里显示的都是PRIMARY,如果是单主模式,就会只显示一个PRIMARY,其他是SECONDARY了。

MGR集群运维相关

全集群重启后如何恢复

当三个节点都重启过后,查看组复制状态如下:

  1. mysql> select * from performance_schema.replication_group_members;
  2. +---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+
  3. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  4. +---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+
  5. | group_replication_applier | | | NULL | OFFLINE | | |
  6. +---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+
  7. 1 row in set (0.00 sec)

好,现在需要在其中一个主节点执行如下指令,以便重新引导集群:

  1. # 开启引导模式
  2. mysql> SET GLOBAL group_replication_bootstrap_group=ON;
  3. Query OK, 0 rows affected (0.00 sec)
  4. # 启动组复制
  5. mysql> start group_replication;
  6. Query OK, 0 rows affected, 1 warning (2.21 sec)
  7. # 查看组成员状态,本节点是否为 ONLINE
  8. mysql> select * from performance_schema.replication_group_members;
  9. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  10. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  11. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  12. | group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  13. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  14. 1 row in set (0.00 sec)
  15. # 关闭引导模式
  16. mysql> SET GLOBAL group_replication_bootstrap_group=OFF;

在剩下其他节点直接开启组复制:

  1. # 开启组复制
  2. mysql> start group_replication;
  3. Query OK, 0 rows affected, 1 warning (2.62 sec)

最后任意一个节点查看组复制状态:

  1. mysql> select * from performance_schema.replication_group_members;
  2. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  3. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  4. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  5. | group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  6. | group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  7. | group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  8. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  9. 3 rows in set (0.35 sec)

至此,MGR集群恢复成功。

MGR三节点集群故障两个节点,如何恢复

停掉两个mysql节点,模拟故障。

分别停止centos-20-2centos-20-4两个节点,如下:

  1. # 只将3306数据库的进程杀掉,守护进程不杀
  2. $ ps -ef | grep mysql | grep -v grep | awk '{print $2}' | tail -1 | xargs kill -9

然后在centos-20-3节点查看集群状态如下:

  1. mysql> select * from performance_schema.replication_group_members;
  2. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  3. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  4. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  5. | group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | UNREACHABLE | PRIMARY | 8.0.26 |
  6. | group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | UNREACHABLE | PRIMARY | 8.0.26 |
  7. | group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  8. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  9. 3 rows in set (0.00 sec)

可以看到停掉进程的那几个节点状态都为:UNREACHABLE

这里说下MEMBER_STATE的不同值都是什么意思:

  • offline:gr插件未启动;
  • recovering:复制加入集群之前产生的数据;
  • online:完成后,可对外服务;
  • error:节点出现错误,gr无法正常运行;
  • unreachable:无法与其他成员通信,网络问题或其他成员非正常退出;

由于此时,三节点集群宕了两个,也就是半数节点都宕了,也就导致集群现在无法写入,集群无法对外服务了。如下:

  1. # 在存活的节点上写入数据会hang住
  2. mysql> insert into test_info values(2,19,'lisi');
  3. # 新开一个窗口,登录到数据库,查看innodb的事务,如下:
  4. mysql> select * from information_schema.innodb_trx\G
  5. *************************** 1. row ***************************
  6. trx_id: 3442
  7. trx_state: RUNNING
  8. trx_started: 2022-01-03 16:10:58
  9. trx_requested_lock_id: NULL
  10. trx_wait_started: NULL
  11. trx_weight: 2
  12. trx_mysql_thread_id: 8
  13. trx_query: insert into test_info values(2,19,'lisi')
  14. trx_operation_state: NULL
  15. trx_tables_in_use: 1
  16. trx_tables_locked: 1
  17. trx_lock_structs: 1
  18. trx_lock_memory_bytes: 1128
  19. trx_rows_locked: 0
  20. trx_rows_modified: 1
  21. trx_concurrency_tickets: 0
  22. trx_isolation_level: READ COMMITTED
  23. trx_unique_checks: 1
  24. trx_foreign_key_checks: 1
  25. trx_last_foreign_key_error: NULL
  26. trx_adaptive_hash_latched: 0
  27. trx_adaptive_hash_timeout: 0
  28. trx_is_read_only: 0
  29. trx_autocommit_non_locking: 0
  30. trx_schedule_weight: NULL
  31. 1 row in set (0.00 sec)
  32. # 进程列表
  33. mysql> show processlist;
  34. +----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
  35. | Id | User | Host | db | Command | Time | State | Info |
  36. +----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
  37. | 5 | event_scheduler | localhost | NULL | Daemon | 5153 | Waiting on empty queue | NULL |
  38. | 8 | root | localhost | ljz | Query | 300 | waiting for handler commit | insert into test_info values(2,19,'lisi') |
  39. | 10 | system user | | NULL | Connect | 4120 | waiting for handler commit | Group replication applier module |
  40. | 13 | system user | | NULL | Query | 4120 | Replica has read all relay log; waiting for more updates | NULL |
  41. | 31 | root | localhost | NULL | Query | 0 | init | show processlist |
  42. +----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
  43. 5 rows in set (0.00 sec)
  44. # kill掉hang住的进程
  45. mysql> kill 8;
  46. Query OK, 0 rows affected (0.00 sec)
  47. # 原来hang住的session会报错如下:
  48. mysql> insert into test_info values(2,19,'lisi');
  49. ERROR 2013 (HY000): Lost connection to MySQL server during query
  50. # 再次查看进程列表
  51. mysql> show processlist;
  52. +----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
  53. | Id | User | Host | db | Command | Time | State | Info |
  54. +----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
  55. | 5 | event_scheduler | localhost | NULL | Daemon | 5707 | Waiting on empty queue | NULL |
  56. | 8 | root | localhost | ljz | Killed | 854 | waiting for handler commit | insert into test_info values(2,19,'lisi') |
  57. | 10 | system user | | NULL | Connect | 4674 | waiting for handler commit | Group replication applier module |
  58. | 13 | system user | | NULL | Query | 4674 | Replica has read all relay log; waiting for more updates | NULL |
  59. | 31 | root | localhost | NULL | Query | 0 | init | show processlist |
  60. | 32 | root | localhost | ljz | Sleep | 184 | | NULL |
  61. +----+-----------------+-----------+------+---------+------+----------------------------------------------------------+-------------------------------------------+
  62. 6 rows in set (0.00 sec)

kill这个hang住的session竟然没有成功,只是显示killed,这个为什么一直显示killed呢,先放着。

看master的错误日志,如下:

  1. 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.'
  2. 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.'
  3. 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参数强制更新组成员

故障恢复

言下之意,将活着的节点,重新组成新集群。那就来试一下:

  1. # 设置为本机的IP+MGR端口
  2. mysql> set global group_replication_force_members = "192.168.20.3:33061";
  3. Query OK, 0 rows affected (6.80 sec)
  4. # 查看MGR状态
  5. mysql> select * from performance_schema.replication_group_members;
  6. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  7. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  8. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  9. | group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  10. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  11. 1 row in set (0.00 sec)
  12. # 插入数据测试
  13. mysql> insert into test_info values(3,19,'lisi');
  14. Query OK, 1 row affected (0.00 sec)
  15. mysql> select * from test_info;
  16. +----+-----+--------+
  17. | id | age | name |
  18. +----+-----+--------+
  19. | 1 | 18 | 张三 |
  20. | 2 | 19 | lisi | # 刚才hang住的那一条记录也被插入进来了
  21. | 3 | 19 | lisi |
  22. +----+-----+--------+
  23. 3 rows in set (0.00 sec)

我们服务现在已经恢复了,后续把节点再加进去即可。

需要注意的是:

  • 加节点,注意每个节点的模式一致,单主还是多主,可以通过show variables like '%group_replication_single_primary_mode%';来确认,如果为OFF,则表明为多主模式,如果为ON,则为单主;
  • 事后最好把group_replication_force_members重新置空,不处理也问题不大;
  • 直接在不可用集群中加节点是加不了的,必须先恢复集群可用才能加节点;

好,我们现在把其他节点都加入到集群中,如下:

  1. # 先将目前的主节点centos-20-3的group_replication_force_members值设置为空
  2. mysql> set global group_replication_force_members = "";
  3. Query OK, 0 rows affected (0.00 sec)

修复故障节点,然后开始组复制:

  1. # 我这边直接重启刚才的故障节点即可修复
  2. $ systemctl restart mysqld
  3. # 登录刚恢复的节点,开启组复制
  4. $ mysql -uroot -p123.com
  5. mysql> start group_replication;

最后在任意一个节点,查看组复制状态如下:

  1. mysql> select * from performance_schema.replication_group_members;
  2. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  3. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  4. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  5. | group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  6. | group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  7. | group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  8. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  9. 3 rows in set (0.01 sec)

MGR监控

这里说是监控,其实就是一些集群中常用的运维用的元数据信息吧

查看节点状态
  1. mysql> select * from performance_schema.replication_group_members;
  2. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  3. | CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
  4. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  5. | group_replication_applier | b3b6dfac-6ae8-11ec-a8c4-000c29f3998c | centos-20-2 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  6. | group_replication_applier | b3c9316a-6ae8-11ec-a895-000c294f94e3 | centos-20-4 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  7. | group_replication_applier | b3d0a667-6ae8-11ec-a81e-000c29784944 | centos-20-3 | 3306 | ONLINE | PRIMARY | 8.0.26 |
  8. +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
  9. 3 rows in set (0.01 sec)

说下member_state字段吧!

含义
offline gr插件未启动
recovering 复制加入集群之前产生的数据
online 完成后,可对外服务
error 节点出现错误,gr无法正常运行
unreachable 无法与其他成员通信,网络问题或其他成员非正常退出

查看成员详细信息

这里注释一些必要字段说明。

  1. mysql> select * from performance_schema.replication_group_member_stats limit 1\G
  2. *************************** 1. row ***************************
  3. CHANNEL_NAME: group_replication_applier
  4. VIEW_ID: 15915014697349018:6 组视图id
  5. MEMBER_ID: a50df330-a4b0-11ea-bfd3-fa163ed6ef91
  6. COUNT_TRANSACTIONS_IN_QUEUE: 0 队列中等待做全局事务认证的事务数量
  7. COUNT_TRANSACTIONS_CHECKED: 2 做了全局事务认证的事务总数量,从加入组开始
  8. COUNT_CONFLICTS_DETECTED: 0 全局事务认证时,有冲突的事务总数量
  9. COUNT_TRANSACTIONS_ROWS_VALIDATING: 0 冲突检测的记录总行数
  10. TRANSACTIONS_COMMITTED_ALL_MEMBERS: 745c2bc6-9fe4-11ea-8c89-fa163e98606f:1-69:1000003-1000005:2000005-2000006 所有事务的gtid集合,相当于gtid_executed交集,非实时,隔段时间更新一次
  11. LAST_CONFLICT_FREE_TRANSACTION: 745c2bc6-9fe4-11ea-8c89-fa163e98606f:67 最后一个没有冲突的事务gtid
  12. COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE: 0 当前节点从gr中接收到的正在等待被应用的事务数量
  13. COUNT_TRANSACTIONS_REMOTE_APPLIED: 5 当前节点从gr中接收的已经应用的事务数量
  14. COUNT_TRANSACTIONS_LOCAL_PROPOSED: 2 当前节点产生并发送给gr的事务数量
  15. COUNT_TRANSACTIONS_LOCAL_ROLLBACK: 0 当前节点产生并被gr回滚的事务数量
  16. 1 row in set (0.00 sec)

其他表
  • replication_connection_status:新节点加入集群,先通过异步复制拉取加入组之前产生的数据,通过这个表监控这个过程;
  • replication_applier_status:group_replication_applier通道来执行binlog event,通过这个表监控这个过程;
  • threads:该表监控gr组件的线程;

注:上述提到的表,都在performance_schema库中。