Appearance
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 --reloadMySQL 二进制安装
此步:每个节点操作一样
官网下载地址: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 编写。
解压并移动安装包
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可能会报错:bashmysqld: 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.cnfbash
[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.servicebash
[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 mysqld2. 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 mysqld3. 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 specifiedMGR组网
注意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;可能导致组网失败sqlCHANGE 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状态,说明集群搭建成功:

可以在主节点建库、建表等,然后在从节点看是否有数据,即可
MGR 故障转移
至此已经将MySQL MGR集群搭建完毕,并且节点都是ONLINE状态

主节点下线,重新选举
在主服务器slave1上停止mysql:
bash
$ systemctl stop mysqld;然后查看集群状态
sql
SELECT * FROM performance_schema.replication_group_members;
MGR 集群选举策略为:
- 优先低版本节点
- 版本一样,优先权重大的节点
- 版本与权重一样,按照 server uuid 的字母顺序选主
在新的主节点上,通过命令查看故障转移日志:
bash
# 查看MySQL日志
$ tail -n 50 /var/log/mysqld.logslave2日志解析大致如下:
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.logslave2 日志解析如下:
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;
恢复 MGR 集群
启动挂掉节点的MySQL,按挂掉的顺序,逆序在MySQL中执行START GROUP_REPLICATION;命令,重新加入集群
法二【未测试】:
恢复流程很简单,先将三台服务器的MySQL各自重启
bash
# 3台服务器都执行
$ systemctl restart mysqld;MySQL重启后会变成如下情况:

开始重新组网
在主节点执行:
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;
然后在从节点执行:
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;
单主模式和多主模式
模式介绍
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;
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;
两种部署模式
在设计上可以和应用层结合起来,有两种部署模式,
应用层双活和数据库双活,应用层双活和数据库单活
MGR集群多活架构
基于MGR的多活特性,数据的写入可以在多个节点之间进行复制,实现数据强一致性需求,并且在节点间通信出现延迟的情况下,会自动实现服务降级。对于此 类方案,我们可以采用同机房多写,同城异机房只读的方案。【主要起到备份的作用】

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

可能遇到的问题
网络不通
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