Skip to content

MGR

什么是 MGR

  • MGR(MySQL Group Replication)是MySQL 5.7.17版本诞生的,是MySQL自带的一个插件,可以灵活部署。
  • 保证数据一致性又可以自动切换,具备故障检测功能、支持多节点写入。
  • 集群是多个MySQL Server节点共同组成的分布式集群,每个Server都有完整的副本,它是基于ROW格式的二进制日志文件和GTID特性。

MGR 优点

  • 强一致性:基于原生复制及paxos协议的组复制技术,并以插件的方式提供,提供一致数据安全保证。
  • 高容错性:只要不是大多数节点坏掉就可以继续工作,有自动检测机制,当不同节点产生资源争用冲突时,不会出现错误,按照先到者优先原则进行处理,并且内置了自动化脑裂防护机制。
  • 高扩展性:节点的新增和移除都是自动的,新节点加入后,会自动从其他节点上同步状态,直到新节点和其他节点保持一致,如果某节点被移除了,其他节点自动更新组信息,自动维护新的组信息。
  • 高灵活性:有单主模式多主模式。单主模式下,会自动选主,所有更新操作都在主上进行;多主模式下,所有server都可以同时处理更新操作。工作中优先使用单主模式!

MGR 缺点

  • 仅支持InnoDB表,并且每张表一定要有一个主键,用于做write set的冲突检测。

  • 必须打开GTID特性,二进制日志格式必须设置为ROW,用于选主与write set;主从状态信息存于表中(–master-info-repository=TABLE 、–relay-log-inforepository=TABLE),–log-slave-updates打开。

  • MGR不支持大事务,事务大小最好不超过143MB,当事务过大,无法在5秒的时间内通过网络在组成员之间复制消息,则可能会怀疑成员失败了,然后将其驱逐出局。

  • 目前一个MGR集群最多支持9个节点

  • 不支持外键于save point特性,无法做全局间的约束检测与部分事务回滚。

  • 二进制日志不支持Binlog Event Checksum。【二进制日志(Binary Log,简称binlog)不启用或不支持对日志事件(Event)的校验和(Checksum)功能】

MGR 适用场景

  • 金融交易、重要数据存储、对主从一致性要求高的场景。
  • 核心数据总量未过亿。
  • 读多写少,如:互联网电商。

基础设置

配置hosts

bash
#将Hosts文件写入slave1/slave2/slave3节点与IP对应关系,后面配置采用域名访问
$ cat > /etc/hosts <<-'EOF'
192.168.31.230 slave1
192.168.31.231 slave2
192.168.31.232 slave3
EOF

修改当前主机的名字

bash
# 修改当前主机的名字
hostnamectl set-hostname slave1
hostnamectl set-hostname slave2
hostnamectl set-hostname slave3

关闭SELinux防火墙

bash
# 大坑:
# 临时关闭 selinux防火墙,开启后端口将无法访问,开发环境可以这样用,如果开启24901默认会被挡住
setenforce 0

# 放行端口,MySQL默认端口: 3306,MGR通信端口: 24901
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --zone=public --add-port=24901/tcp --permanent
firewall-cmd --reload

MySQL 二进制安装

此步:每个节点操作一样

官网下载地址:https://dev.mysql.com/downloads/mysql/ 下载 Community(社区版) 的 generic(通用版) 二进制包文件。

查看mariadb是否存在

bash
$ rpm -qa | grep mariadb                  # 查看是否存在mariadb安装
$ rpm -e  --nodeps  mariadb-libs          # 卸载包。 --nodeps 不检验依赖
bash
# 查看当前系统文件库版本:
$ ldd --version

执行样例

bash
$ ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 Roland McGrath Ulrich Drepper 编写。

image-20240710204229579

解压并移动安装包

bash
# 解压 tar -zxvf 待解压目录
$ tar -xf mysql-8.0.35-linux-glibc2.17-x86_64.tar.xz

# 移动 mv 移动目录 移动后的目录
$ mv mysql-8.0.35-linux-glibc2.17-x86_64 /data/mysql

创建数据目录

bash
# 进入MySQL目录
$ cd /data/mysql

# 创建data,logs文件夹(也可以根据那个磁盘大而定  --df -Th查看)
$ mkdir /data/mysql/{data,logs}
$ mkdir /etc/my.cnf.d

不创建目录/etc/my.cnf.d可能会报错:

bash
mysqld: Can't read dir of '/etc/my.cnf.d' (OS errno 2 - No such file or directory)
mysqld: [ERROR] Stopped processing the 'includedir' directive in file /etc/my.cnf at line 52.
mysqld: [ERROR] Fatal error in defaults handling. Program aborted!

创建mysql用户权限

bash
# 创建mysql用户并添加到mysql组中,系统用户无登陆模式
$ useradd -s /sbin/nologin mysql

# 修改mysql目录的组以及权限
$ chown mysql:mysql -R /data/mysql

修改MySQL配置文件

vi /etc/my.cnf
bash
[mysqld]
character_set_server=utf8

port = 3306
basedir = /data/mysql
datadir = /data/mysql/data
socket = /tmp/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd

default_authentication_plugin=mysql_native_password
plugin_dir=/data/mysql/lib/plugin
# 服务器编号【与从节点不一样】
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE

# 定义用于事务期间哈希写入提取的算法,组复制模式下必须设置为 XXHASH64【与从节点不一样,从没有】
transaction_write_set_extraction=XXHASH64
loose-group_replication_recovery_use_ssl=ON
loose-group_replication_group_name="bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee"
loose-group_replication_start_on_boot=OFF
# 当前节点地址【与从节点不一样】
loose-group_replication_local_address="slave1:24901"
loose-group_replication_group_seeds="slave1:24901,slave2:24901,slave3:24901"

loose-group_replication_bootstrap_group=OFF

[mysqld_safe]
log-error=/data/mysql/logs/mysql.log
#pid-file=/data/mysql/data/mysqld.pid
pid-file=/var/run/mysql/mysql.pid

# 日志记录慢查询SQL
slow_query_log = true
slow_query_log_file = /data/mysql/logs/mysql_slow_query.log
long_query_time = 1

# 设置sql_mode行为规则
sql_mode = 'NO_ENGINE_SUBSTITUTION'

# 设置binlog过期时间,过期自动删除 binlog_expire_logs_seconds单位是秒
binlog_expire_logs_seconds = 604800
max_binlog_size = 100M
log_bin_trust_function_creators = 1

#
# include all files from the config directory
#
!includedir /etc/my.cnf.d

从节点与主节点的区别

sql
# 每个节点都不一样的地方
## 服务器编号【每个节点都不一样】
server_id=1
## 当前节点地址【每个节点都不一样】
loose-group_replication_local_address="slave1:24901"

# 以下两项配置主从不一样
# 定义用于事务期间哈希写入提取的算法,组复制模式下必须设置为 XXHASH64【与从节点不一样,从没有】
transaction_write_set_extraction=XXHASH64
# 这个参数决定 primary节点 到 secondary节点 的请求是否为基于 RSA 密钥对的密码交换所需的公钥【与主节点不一样,主没有】
loose-group_replication_recovery_get_public_key=ON

初始化MySQL

bash
# 初始化  --defaults-file为配置文件所在 ,--basedir为解压路径,--datadir为数据保存路径 --user表示MySQL所属用户
$ ./bin/mysqld --defaults-file=/etc/my.cnf --basedir=/data/mysql/ --datadir=/data/mysql/data --user=mysql --initialize

执行样例

bash
$ ./bin/mysqld --defaults-file=/etc/my.cnf --basedir=/data/mysql/ --datadir=/data/mysql/data --user=mysql --initialize
2024-07-12T16:44:55.510023Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
2024-07-12T16:44:55.510054Z 0 [Warning] [MY-011069] [Server] The syntax '--transaction-write-set-extraction' is deprecated and will be removed in a future release.
2024-07-12T16:44:55.510923Z 0 [Warning] [MY-010918] [Server] 'default_authentication_plugin' is deprecated and will be removed in a future release. Please use authentication_policy instead.
2024-07-12T16:44:55.510950Z 0 [System] [MY-013169] [Server] /data/mysql/bin/mysqld (mysqld 8.0.35) initializing of server in progress as process 78144
2024-07-12T16:44:55.512595Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
2024-07-12T16:44:55.529641Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2024-07-12T16:44:56.438032Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2024-07-12T16:44:59.248193Z 0 [Warning] [MY-000067] [Server] unknown variable 'loose-group_replication_recovery_use_ssl=ON'.
2024-07-12T16:44:59.248221Z 0 [Warning] [MY-000067] [Server] unknown variable 'loose-group_replication_group_name=bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee'.
2024-07-12T16:44:59.248227Z 0 [Warning] [MY-000067] [Server] unknown variable 'loose-group_replication_start_on_boot=OFF'.
2024-07-12T16:44:59.248232Z 0 [Warning] [MY-000067] [Server] unknown variable 'loose-group_replication_local_address=slave1:24901'.
2024-07-12T16:44:59.248237Z 0 [Warning] [MY-000067] [Server] unknown variable 'loose-group_replication_group_seeds=slave1:24901,slave2:24901,slave3:24901'.
2024-07-12T16:44:59.248241Z 0 [Warning] [MY-000067] [Server] unknown variable 'loose-group_replication_bootstrap_group=OFF'.
2024-07-12T16:44:59.250038Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: Q6*n!K;0kXpo
2024-07-12T16:44:59.475615Z 6 [Warning] [MY-013360] [Server] Plugin mysql_native_password reported: ''mysql_native_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'

初始化后会有密码产生,记录最后一行密码 Q6*n!K;0kXpo

若控制台没有输出,可以尝试

bash
$ grep 'temporary password' /var/log/mysqld.log
$ grep 'temporary password' /data/mysql/logs/mysqld.log

设置systemd启动文件

bash
$ vi /usr/lib/systemd/system/mysqld.service
bash
[Unit]
Description=MySQL Server
Documentation=man:mysqld()
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql
PIDFile=/data/mysql/data/mysqld.pid

# Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=

# Execute pre and post scripts as root
PermissionsStartOnly=true
# Needed to create system tables
#ExecStartPre=/usr/bin/mysqld_pre_systemd

# Start main service
ExecStart=/data/mysql/bin/mysqld --daemonize --pid-file=/data/mysql/data/mysqld.pid
#注意这里要加上 --daemonize
# Use this to switch malloc implementation
#EnvironmentFile=-/etc/sysconfig/mysql

# Sets open_files_limit
LimitNOFILE =
Restart=on-failure
RestartPreventExitStatus=
PrivateTmp=false

启动服务

bash
# 开机自启动
$ systemctl enable mysqld.service
$ systemctl start mysqld.service

# 设置环境变量
$ vi /etc/profile
export PATH=$PATH:/data/mysql/bin		## 最后一行添加

$ source /etc/profile

修改密码

使用初始密码登录MySQL

bash
$ mysql -uroot -p'密码'
# 样例
$ mysql -uroot -p'Q6*n!K;0kXpo'

改root密码

bash
# 修改root密码为Liulike#123!
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'Liulike#123!';

# 创建一个远程连接用户,【可选操作,通常不会直接使用root用户远程】
create user 'remote'@'%' identified with mysql_native_password by 'Liulike#123!';
# 为remote用户赋予所有数据库资源的访问权限,熟悉grant的可以自己调整
grant all privileges on *.* to remote@'%';

# 设置 root 远程登录
use mysql;
update user set user.Host='%' where user.User='root';
flush privileges;

# 让刚才的修改生效
FLUSH PRIVILEGES;

# 大坑:
# 删除已产生的Binlog
# 一定要 RESET MASTER,它会删除刚才已产生的Binlog
# 因为刚才Binglog包含创建用户这种高权限操作,用于主从同步的 rpl_user 账户是没有权限执行的
# 这就会导致 RelayLog 重放无法正确执行,导致从属服务器卡死在 "RECEVING" 状态
# 利用 RESET MASTER 删除这些无法执行的binlog,就没问题了
RESET MASTER;

MySQL MGR 搭建流程

调整配置文件

实际上前面my.cnf已经配置了,这里主要说明MGR相关的配置 主从三个节点配置文件是不同的

1. slave1节点

shell
# 安装完成,追加mysql
cat >> /etc/my.cnf <<-'EOF'
# 使用 mysql_native_password 密码策略,防止navicat连不上mysq18
default_authentication_plugin=mysql_native_password
# 设置 MySQL插件 所在目录,因为 MGR 基于插件,所以必须设置插件路径
plugin_dir=/usr/lib64/mysql/plugin
# 服务器编号【每个节点都不一样】
server_id=1
# 开启binlog的GTID模式
gtid_mode=ON
# 开启后 MySQL只允许能够保障事务安全,并且能够被日志记录的SQL语句被执行
enforce_gtid_consistency=ON
# 关闭binlog校验
binlog_checksum=NONE

# 定义用于事务期间哈希写入提取的算法,组复制模式下必须设置为 XXHASH64【与从节点不一样,从没有】
transaction_write_set_extraction=XXHASH64
# 确定组复制恢复时是否应该应用 SSL,通常设置为“开”,但默认设置为“关”
loose-group_replication_recovery_use_ssl=ON
# 该服务器的实例所在复制组的名称,必须是有效的UUID,所有节点必须相同。
loose-group_replication_group_name="bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee"
# 确定服务器是否应该在服务器启动期间启动组复制。
loose-group_replication_start_on_boot=OFF

# 大坑:【每个节点都不一样】
# 为复制组中其他的成员提供的网络地址,指定为“主机:端口”的格式化字符串。
# 很多人想当然认为端口应该是3386,其实不然,MGR需要开启新端口24901同步交换
# 所以这里不要写错,同时,前面我们配置了hosts文件做了主机名与IP的映射,这里直接写主机名即可
loose-group_replication_local_address="slave1:24901"

# 用于建立新成员到组的连接组成员列表
# 这个列表指定为由分隔号间隔的组成员网络地址列表,类似 host1:port1、host2:port2 的格式
# 同样采用slave1~slave3的主机名替代
loose-group_replication_group_seeds="slave1:24901,slave2:24901,slave3:24901"

# 配置此服务器为引导组,这个选项必须仅在一台服务器上设置
# 并且仅当 第一次启动组 或者 重新启动整个组 时。成功引导组启动后,将此选项设置为关闭
loose-group_replication_bootstrap_group=OFF
EOF

启动MySQL服务器

bash
$ systemctl start mysqld

2. slave2节点

bash
# 安装完成,追加mysql
cat >> /etc/my.cnf <<-'EOF'
# 使用 mysql_native_password 密码策略,防止navicat连不上mysq18
default_authentication_plugin=mysql_native_password
# 设置 MySQL插件 所在目录,因为 MGR 基于插件,所以必须设置插件路径
plugin_dir=/usr/lib64/mysql/plugin
# 服务器编号【每个节点都不一样】
server_id=2
# 开启binlog的GTID模式
gtid_mode=ON
# 开启后 MySQL只允许能够保障事务安全,并且能够被日志记录的SQL语句被执行
enforce_gtid_consistency=ON
# 关闭binlog校验
binlog_checksum=NONE

# 这个参数决定 primary节点 到 secondary节点 的请求是否为基于 RSA 密钥对的密码交换所需的公钥【与主节点不一样,主没有】
loose-group_replication_recovery_get_public_key=ON
# 确定组复制恢复时是否应该应用 SSL,通常设置为“开”,但默认设置为“关”
loose-group_replication_recovery_use_ssl=ON
# 该服务器的实例所在复制组的名称,必须是有效的UUID,所有节点必须相同。
loose-group_replication_group_name="bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee"
# 确定服务器是否应该在服务器启动期间启动组复制。
loose-group_replication_start_on_boot=OFF

# 大坑:【每个节点都不一样】
# 为复制组中其他的成员提供的网络地址,指定为“主机:端口”的格式化字符串。
# 很多人想当然认为端口应该是3386,其实不然,MGR需要开启新端口24901同步交换
# 所以这里不要写错,同时,前面我们配置了hosts文件做了主机名与IP的映射,这里直接写主机名即可
loose-group_replication_local_address="slave2:24901"

# 用于建立新成员到组的连接组成员列表
# 这个列表指定为由分隔号间隔的组成员网络地址列表,类似 host1:port1、host2:port2 的格式
# 同样采用slave1~slave3的主机名替代
loose-group_replication_group_seeds="slave1:24901,slave2:24901,slave3:24901"

# 配置此服务器为引导组,这个选项必须仅在一台服务器上设置
# 并且仅当 第一次启动组 或者 重新启动整个组 时。成功引导组启动后,将此选项设置为关闭
loose-group_replication_bootstrap_group=OFF
EOF

启动MySQL服务器

bash
$ systemctl start mysqld

3. slave3节点

shell
# 安装完成,追加mysql
cat >> /etc/my.cnf <<-'EOF'
# 使用 mysql_native_password 密码策略,防止navicat连不上mysq18
default_authentication_plugin=mysql_native_password
# 设置 MySQL插件 所在目录,因为 MGR 基于插件,所以必须设置插件路径
plugin_dir=/usr/lib64/mysql/plugin
# 服务器编号【每个节点都不一样】
server_id=3
# 开启binlog的GTID模式
gtid_mode=ON
# 开启后 MySQL只允许能够保障事务安全,并且能够被日志记录的SQL语句被执行
enforce_gtid_consistency=ON
# 关闭binlog校验
binlog_checksum=NONE

# 这个参数决定 primary节点 到 secondary节点 的请求是否为基于 RSA 密钥对的密码交换所需的公钥【与主节点不一样,主没有】
loose-group_replication_recovery_get_public_key=ON
# 确定组复制恢复时是否应该应用 SSL,通常设置为“开”,但默认设置为“关”
loose-group_replication_recovery_use_ssl=ON
# 该服务器的实例所在复制组的名称,必须是有效的UUID,所有节点必须相同。
loose-group_replication_group_name="bbbbbbbb-bbbb-cccc-dddd-eeeeeeeeeeee"
# 确定服务器是否应该在服务器启动期间启动组复制。
loose-group_replication_start_on_boot=OFF

# 大坑:【每个节点都不一样】
# 为复制组中其他的成员提供的网络地址,指定为“主机:端口”的格式化字符串。
# 很多人想当然认为端口应该是3386,其实不然,MGR需要开启新端口24901同步交换
# 所以这里不要写错,同时,前面我们配置了hosts文件做了主机名与IP的映射,这里直接写主机名即可
loose-group_replication_local_address="slave3:24901"

# 用于建立新成员到组的连接组成员列表
# 这个列表指定为由分隔号间隔的组成员网络地址列表,类似 host1:port1、host2:port2 的格式
# 同样采用slave1~slave3的主机名替代
loose-group_replication_group_seeds="slave1:24901,slave2:24901,slave3:24901"

# 配置此服务器为引导组,这个选项必须仅在一台服务器上设置
# 并且仅当 第一次启动组 或者 重新启动整个组 时。成功引导组启动后,将此选项设置为关闭
loose-group_replication_bootstrap_group=OFF
EOF

启动MySQL服务器

bash
$ systemctl start mysqld

设置主从同步账户

设置主从同步账户

sql
# 登录
mysql -uroot -p'Liulike#123!'

# 创建 rpl_user 账户,此账户用于实现主从数据同步【从属节点可以不创建rpl_user用户】
CREATE USER rpl_user@'%' IDENTIFIED BY 'Liulike#123!';
# 赋予主从同步权限
GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';

# 让刚才的修改生效
FLUSH PRIVILEGES;

# 大坑:
# 删除已产生的Binlog
# 一定要 RESET MASTER,它会删除刚才已产生的Binlog
# 因为刚才Binglog包含创建用户这种高权限操作,用于主从同步的 rpl_user 账户是没有权限执行的
# 这就会导致 RelayLog 重放无法正确执行,导致从属服务器卡死在 "RECEVING" 状态
# 利用 RESET MASTER 删除这些无法执行的binlog,就没问题了
RESET MASTER;

安装MGR同步插件

在MySQL操作,部署服务器命令行

因为配置文件指明了插件目录,且MySQL8内置了这个插件,所以可以直接使用以下命令安装

所有节点都需要安装

sql
INSTALL PLUGIN group_replication SONAME 'group_replication.so';

判断是否安装成功

sql
SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'group_replication' \G;

运行SQL如果出现 PLUGIN STATUS: ACTIVE 插件状态为ACTIVE,则表示安装成功

执行样例:

sql
mysql> SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'group_replication' \G;
*************************** 1. row ***************************
           PLUGIN_NAME: group_replication
        PLUGIN_VERSION: 1.1
         PLUGIN_STATUS: ACTIVE
           PLUGIN_TYPE: GROUP REPLICATION
   PLUGIN_TYPE_VERSION: 1.4
        PLUGIN_LIBRARY: group_replication.so
PLUGIN_LIBRARY_VERSION: 1.11
         PLUGIN_AUTHOR: Oracle Corporation
    PLUGIN_DESCRIPTION: Group Replication (1.1.0)
        PLUGIN_LICENSE: GPL
           LOAD_OPTION: ON
1 row in set (0.00 sec)

ERROR: 
No query specified

MGR组网

注意my.cnf配置文件内

1. 组网

主服务器执行

sql
# 注意:只在主服务器上运行
# 我们在 my.cnf 配置文件中把 group_replication_bootstrap_group 参数设置成 OFF
# 在 主服务器 启动时并不会直接启动复制组,通过下面的命令动态的开启复制组是我们的集群更安全
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

从属服务器执行

sql
# 指定 主从账户信息 与 指定通信频道
CHANGE MASTER TO MASTER_USER="rpl_user", MASTER_PASSWORD="Liulike#123!" FOR CHANNEL 'group_replication_recovery';

# 开启组网数据同步
START GROUP_REPLICATION;

START时没有报错,结果时Query OK表示设置是没啥问题的,但是不表示完成了同步,后续还需要在主服务器执行SQL验证

超大坑

指定 主从账户信息 与 指定通信频道时记得在主节点上也添加,否则初始主节点宕机后直接使用START GROUP_REPLICATION;可能导致组网失败

sql
CHANGE MASTER TO MASTER_USER="rpl_user", MASTER_PASSWORD="Liulike#123!" FOR CHANNEL 'group_replication_recovery';

2. 验证

从节点都运行完毕后,运行下面SQL结果进行验证

sql
SELECT * FRoM performance_schema.replication_group_members;

查看

MEMBER ROLE:主——>PRIMARY,从——>SECONLARY

MEMBER STATE:正常——>ONLINE

出现以下情况,每个节点都是ONLINE状态,说明集群搭建成功:

image-20240712170034393

可以在主节点建库、建表等,然后在从节点看是否有数据,即可

MGR 故障转移

至此已经将MySQL MGR集群搭建完毕,并且节点都是ONLINE状态

image-20240712170034393

主节点下线,重新选举

在主服务器slave1上停止mysql:

bash
$ systemctl stop mysqld;

然后查看集群状态

sql
SELECT * FROM performance_schema.replication_group_members;

image-20240712171357481

MGR 集群选举策略为:

  • 优先低版本节点
  • 版本一样,优先权重大的节点
  • 版本与权重一样,按照 server uuid 的字母顺序选主

在新的主节点上,通过命令查看故障转移日志:

bash
# 查看MySQL日志
$ tail -n 50 /var/log/mysqld.log

slave2日志解析大致如下:

bash
# slave1:3306(主节点slave1)从组中被移除掉
[Warning] [MY-011499] [Repl] Plugin group_replication reported: 'Members removed from the group: slave1:3306'

# 重新选举新的 Primary 主节点
[System] [MY-011500] [Repl] Plugin group_replication reported: 'Primary server with address slave1:3306 left the group. Electing new Primary.'

# slave2:3306(从节点slave2)被选举为主节点,执行之前未完成的事务处理
[System] [MY-011507] [Repl] Plugin group_replication reported: 'A new primary with address slave2:3306 was elected. The new primary will execute all previous group transactions before allowing writes.'

# 组成员目前只剩 slave2:3306, slave3:3306
[System] [MY-011503] [Repl] Plugin group_replication reported: 'Group membership changed to slave2:3306, slave2:3306 on view 17172171443362674:4.'

# 关闭 slave2 节点的只读状态
[System] [MY-013731] [Repl] Plugin group_replication reported: 'The member action "mysql_disable_super_read_only_if_primary" for event "AFTER_PRIMARY_ELECTION" with priority "1" will be run.'

# 设置 super_read_only=OFF
[System] [MY-011566] [Repl] Plugin group_replication reported: 'Setting super_read_only=OFF.'

# 当前节点(slave2)以主节点身份工作
[System] [MY-011510] [Repl] Plugin group_replication reported: 'This server is working as primary member.'

在slave3从节点上,通过命令查看故障转移日志:

bash
# 查看MySQL日志
$ tail -n 50 /var/log/mysqld.log

slave2 日志解析如下:

bash
# slave1:3306(主节点slave1)从组中被移除掉
[Warning] [MY-011499] [Repl] Plugin group_replication reported: 'Members removed from the group: slave1:3306'

# 重新选举新的 Primary 主节点
[System] [MY-011500] [Repl] Plugin group_replication reported: 'Primary server with address slave1:3306 left the group. Electing new Primary.'

# slave2:3306(从节点slave2)被选举为主节点,执行之前未完成的事务处理
[System] [MY-011507] [Repl] Plugin group_replication reported: 'A new primary with address slave2:3306 was elected. The new primary will execute all previous group transactions before allowing writes.'

# 组成员目前只剩 slave2:3306, slave3:3306
[System] [MY-011503] [Repl] Plugin group_replication reported: 'Group membership changed to slave2:3306, slave3:3306 on view 17172171443362674:4.'

# 当前节点(slave3)作为主节点(slave2)的从成员身份工作
[System] [MY-011511] [Repl] Plugin group_replication reported: 'This server is working as secondary member with primary member address slave2:3306.'

新主节点下线,集群不可用

当在新晋升的主节点上停止MySQL:

bash
$ systemctl stop mysqld;

此时,在最后一个从节点【当前集群只有两个从哈】上通过命令查看发现,slave2主节点尽管已经下线,但slave2查看集群状态时还在显示,因为只有1个节点的情况下,少于n/2+1的规则,导致整体 MGR 集群失效,slave2节点无法产生重新选举,同时slave2的日志也不会有任何新内容产生:

sql
SELECT * FROM performance_schema.replication_group_members;

image-20240712171656843

恢复 MGR 集群

启动挂掉节点的MySQL,按挂掉的顺序,逆序在MySQL中执行START GROUP_REPLICATION;命令,重新加入集群

法二【未测试】:

恢复流程很简单,先将三台服务器的MySQL各自重启

bash
# 3台服务器都执行
$ systemctl restart mysqld;

MySQL重启后会变成如下情况:

image-20240712171948059

开始重新组网

在主节点执行:

sql
# 在主节点执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

执行完后查看状态,发现自己加入了集群

sql
SELECT * FRoM performance_schema.replication_group_members;

image-20240712172123595

然后在从节点执行:

sql
CHANGE MASTER TO MASTER_USER="rpl_user", MASTER_PASSWORD="Liulike#123!" FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

执行完后再次查看状态,发现从属节点加入了集群

sql
SELECT * FRoM performance_schema.replication_group_members;

image-20240712172536580

单主模式和多主模式

模式介绍

1. 单主模式

在单主模式下, 组复制具有自动选主功能,每次只有一个 server成员可以作为主节点。

单主模式 group 内只有一台节点可写可读,其他节点只可以读。对于group的部署,需要先跑起主节点,然后再跑起其他的从节点,并把这些节点加进group。其他的节点就会自动同步主节点上面的变化,然后将自己设置为只读模式。

当主节点意外宕机或者下线,在满足大多数节点存活的情况下,group内部发起选举,选出下一个可用的读节点,提升为新的主节点。

单主模式

2. 多主模式

在多主模式下,所有的 MySQL 节点都可以同时接受读写操作。group内的所有节点都是主节点,同时可以进行读写操作,并且数据是最终一致的。

单主模式

模式切换

上文搭建的 MySQL MGR 集群就是单主模式(默认),切换为多主模式按照如下操作进行

1. 单主 —> 多主

从 slave1 ~ slave3 停止组复制,开启多主模式(3个节点都执行):

sql
# 停止组复制
stop group_replication;

# 是否启用单主模式,默认ON,OFF代表多主
set global group_replication_single_primary_mode=OFF;

# 是否开启条件检查,因为多主的约束更为严格,不符合要求的直接拒绝
# 不支持外键的级联操作
# 不支持 “串行化Serializable”
set global group_replication_enforce_update_everywhere_checks=ON;

在 slave1 主节点启用组复制:

sql
# 只在 slave1 上执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

在 slave2,slave3 节点上启用组复制:

sql
# 只在 slave2, slave3 上执行
START GROUP_REPLICATION;

此时,可以看到三台MySQL都是主节点:

sql
SELECT * FROM performance_schema.replication_group_members;

image-20240712172846654

2. 多主 —> 单主

从 slave1 ~ slave3 停止组复制,开启多主模式(3个节点都执行):

sql
# 停止组复制
stop group_replication;

# 是否开启条件检查,因为多主的约束更为严格,不符合要求的直接拒绝
# 不支持外键的级联操作
# 不支持“串行化Serializable”
set global group_replication_enforce_update_everywhere_checks=OFF;

# 是否启用单主模式,默认ON,OFF代表多主
set global group_replication_single_primary_mode=ON;

在 slave1 主节点启用组复制:

sql
# 只在 slave1 上执行
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

在 slave2,slave3 节点上启用组复制:

sql
# 只在 slave2, slave3 上执行
START GROUP_REPLICATION;

此时,可以看到三台MySQL变成了主从模式:

sql
SELECT * FROM performance_schema.replication_group_members;

image-20240712173041191

两种部署模式

在设计上可以和应用层结合起来,有两种部署模式,应用层双活数据库双活应用层双活数据库单活

MGR集群多活架构

基于MGR的多活特性,数据的写入可以在多个节点之间进行复制,实现数据强一致性需求,并且在节点间通信出现延迟的情况下,会自动实现服务降级。对于此 类方案,我们可以采用同机房多写,同城异机房只读的方案。【主要起到备份的作用】

image-20240712173041191

双主模式的多活

两个节点均可以写入数据,可以实现跨机房的数据复制,延迟较低,在业务层需要做隔离,在故障发生时能够快速切换到同机房的Slave节点。此方案对于两个 IDC机房的场景中较为实用,但是机房多活的场景不适合。

image-20240712173041191

可能遇到的问题

网络不通

bash
$ tail -f /var/log/mysqld.log 看日志
[ERROR] [MY-011735] [Repl] Plugin group_replication reported: '[GCS] Error joining the group while waiting for the network layer to become ready.'

解决办法: ping slave1、ping slave2、ping slave3 确保网络畅通 所有节点千万不要忘记执行: setenforce 0

事务进度不一致

bash
$ tail -f /var/log/mysqld.log 看日志
[Warning] Plugin group_replication reported:
This member has more executed transactions than those present in the group.
Local transactions: f9418f39-8f6a-11ea-8e60-005056841c10:1> Group transactions: 6cd784d-8f66-11ea-bd2e-005056
аaaaaaaa-aaaa-aaaa-aaaа-аaaaaaaaaaaa:1-5'

解决办法:从属服务器停止,RESET binlog,重新同步

sql
STOP GROUP_REPLICATION;
RESET MASTER;
CHANGE MASTER TO MASTER_USER="rpl_user", MASTER_PASSWORD="Liulike#123!" FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

无法执行create user..

bash
$ tail -f/var/log/mysqld.log 看日志
如果Slave节点日志出现 Can not execute query: "create user"

代表某一条SQL的执行权限已经超过roluser用户的执行权眼,会导致从节点同步状态卡死在"RECEVING"状态 解决办法:主节点执行REST MASTER,重新同步。这适用于刚开始的情况,运行中出现可以使用指令忽略这条无法同步的binlog