暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL 组复制-搭建

数据库不跑路 2021-04-25
1288

为了便于深入了解 MGR,如果能有一个现成的集群,就能大大方便我们的实验和研究。本篇介绍如何基于 docker+MySQL 官方镜像在开发机搭建 MGR 集群

实验环境:

  • 4C16G 开发机
  • Ubuntu 18.04
  • docker 19
  • MySQL 8.0.18(3 节点)

docker 安装

先移除系统中的老版本 docker

sudo apt-get remove docker docker-engine docker.io containerd runc

添加 docker 源

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -s
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"s
sudo apt update

安装 docker 本体

sudo apt-get install docker-ce docker-ce-cli containerd.io

配置文件准备

准备一个如下结构的目录

.
├── node1
│   ├── conf
│   │   └── my.cnf
│   └── data
├── node2
│   ├── conf
│   │   └── my.cnf
│   └── data
└── node3
├── conf
│   └── my.cnf
└── data

其中,每个 nodex 对应一个节点。my.cnf 为配置文件,data 目录作为 mysql 的 datadir

my.cnf 写入配置

# only the last two sub-sections are directly related to Group Replication
[mysqld]
server-id = 1
bind_address = 0.0.0.0
#datadir=/var/lib/mysql
#socket=/var/lib/mysql/mysql.sock

#log-error=/var/log/mysqld.log
#pid-file=/var/run/mysqld/mysqld.pid

# SSL options
#ssl-ca = ca.pem
#ssl-cert = server-cert.pem
#ssl-key = server-key.pem
default_authentication_plugin = mysql_native_password

# replication and binlog related options
binlog-row-image = MINIMAL
binlog-rows-query-log-events = ON
log-bin-trust-function-creators = TRUE
expire-logs-days = 90
max-binlog-size = 1G
relay-log-recovery = ON
slave-parallel-type = LOGICAL_CLOCK
slave-preserve-commit-order = ON
slave-parallel-workers = 8
slave-rows-search-algorithms = 'INDEX_SCAN,HASH_SCAN'
slave-type-conversions = ALL_NON_LOSSY
sync-master-info = 1000
sync-relay-log = 1000

# group replication pre-requisites & recommendations
log-bin
binlog-format = ROW
gtid-mode = ON
enforce-gtid-consistency = ON
log-slave-updates = ON
master-info-repository = TABLE
relay-log-info-repository = TABLE
binlog-checksum = NONE
# prevent use of non-transactional storage engines
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE"
# InnoDB gap locks are problematic for multi-primary conflict detection; none are used with READ-COMMITTED
# So if you don't rely on REPEATABLE-READ semantics and/or wish to use multi-primary mode then this
# isolation level is recommended
transaction-isolation = 'READ-COMMITTED'

# group replication specific options
plugin-load = group_replication.so
group_replication = FORCE_PLUS_PERMANENT
transaction-write-set-extraction = XXHASH64
group_replication_start_on_boot = OFF
group_replication_bootstrap_group = OFF
group_replication_group_name = 550fa9ee-a1f8-4b6d-9bfe-c03c12cd1c72
group_replication_local_address = 'mysql3306:6606'
group_replication_group_seeds = 'mysql3306:6606,mysql3307:6606,mysql3308:6606'

注意

  • server-id,每个 node 必须不一样,作为一个 node 的唯一标示
  • 最后一节 group replication specific options 的配置必须先注释,在 docker 容器初始化完成之后再打开,否则 mysql 在初始化阶段会失败

启动集群

配置文件准备完之后,我们可以开始动起集群了

mysql 初始化

在 node1 目录下执行

docker run -p 3306:3306 --name mysql3306 -v $PWD/conf:/etc/mysql/conf.d -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.18

命令含义

  • -p, 容器端口映射到主机
  • --name, 给容器起别名
  • -v, 挂载主机文件夹到容器内部,这里挂载了配置和数据目录
  • -e, 传给容器的初始化参数,这里用来设置 root 的密码
  • -d, 容器放后台运行

观察 docker 日志

docker logs -f -t mysql3306

当观察到如下日志后,表明 mysql 初始化完成

/usr/sbin/mysqld: ready for connections. Version: '8.0.18'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

以同样的方法初始化其他两个节点,分别命名为mysql3307
mysql3308
,映射对应端口。

一切顺利的话,docker ps
能观察到 3 个容器正在运行

CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                               NAMES
7d66a405d10b mysql:8.0.18 "docker-entrypoint.s…" 34 seconds ago Up 32 seconds 33060/tcp, 0.0.0.0:3308->3306/tcp mysql3308
7bc0016d5d81 mysql:8.0.18 "docker-entrypoint.s…" About a minute ago Up About a minute 33060/tcp, 0.0.0.0:3307->3306/tcp mysql3307
c10352cde0dd mysql:8.0.18 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql3306

docker 网络初始化

创建一个 docker network,并将 3 个容器连接到网络中,便于在 docker 内部用容器名访问

docker network create mgr
docker network connect mgr mysql3306
docker network connect mgr mysql3307
docker network connect mgr mysql3308

bootstrap 节点

我们以 node1(主机 3306 端口)作为 bootstrap 节点,引导整个集群的初始化。注意,必须有一个 bootstrap 节点

将前面注释掉的group replication specific options
配置注释回来,注意以下两个配置

# 本机地址,容器名:6606,MGR内部通信地址
group_replication_local_address = 'mysql3306:6606'
# 集群连接地址,固定把3个都写进来
group_replication_group_seeds = 'mysql3306:6606,mysql3307:6606,mysql3308:6606'

修改完成之后重启容器

docker restart mysql3306 mysql3307 mysql3308

用 mysql 标准客户端连接 3306 端口,执行如下 sql 启动 mgr 的 bootstrap 节点

-- 创建用户
CREATE USER repl@'%' IDENTIFIED WITH mysql_native_password BY 'repl';
GRANT REPLICATION SLAVE ON *.* TO repl@'%';
FLUSH PRIVILEGES;

-- 设置bootstrap节点
set global group_replication_bootstrap_group=ON;

-- 设置mgr
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';

-- 重置binlog
reset master;

-- 启动mgr
start group_replication;

此时可以观察到 mgr 集群已启动,并且已经 bootstrap 节点已经在里面了

mysql> select * from performance_schema.replication_group_members\G
*************************** 1. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: 7257bfc2-195d-11ea-83c0-0242ac110002
MEMBER_HOST: c10352cde0dd
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.18
1 row in set (0.00 sec)

其他节点启动

同 bootstrap 节点一样启动其他节点,除了不要以下设置

set global group_replication_bootstrap_group=ON;

注意:由于 mysql 容器在初始化的过程中,初始化了几个表,执行了几个事务,一定不能漏了reset master
,否则会报 gtid 事务冲突

一切顺利的话可以看到单 master 的 MGR 集群已经初始化完成

mysql> select * from performance_schema.replication_group_members\G
*************************** 1. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: 1058a26d-195e-11ea-a315-0242ac110004
MEMBER_HOST: 7d66a405d10b
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.18
*************************** 2. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: 7257bfc2-195d-11ea-83c0-0242ac110002
MEMBER_HOST: c10352cde0dd
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.18
*************************** 3. row ***************************
CHANNEL_NAME: group_replication_applier
MEMBER_ID: eecae6ce-195d-11ea-b6fc-0242ac110003
MEMBER_HOST: 7bc0016d5d81
MEMBER_PORT: 3306
MEMBER_STATE: ONLINE
MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.18
3 rows in set (0.00 sec)

由于是在 docker 内部,所以MEMBER_HOST
为容器的 hostname,即 container id;MEMBER_PORT
都为内部观察到的 3306。

读写测试

此时,在 3306 节点上创建一个表,写入数据,会在其他节点中传播开来。

如果在 3307 或 3308 节点上做写入操作,会报ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
,因为现在还是单主模式,只能在 primary 节点写入,secondary 节点只读

集群模式切换

从 8.0.17 开始,mysql 提供了 UDF 来在单主和多主模式之间切换,而且不用重启进程

-- 切换到多主
SELECT group_replication_switch_to_multi_primary_mode();

-- 切换到单主模式,uuid为切换后的primary
SELECT group_replication_switch_to_single_primary_mode(member_uuid);

结论

至此,MGR 集群已经搭建完毕,可以进行各项特性测试了,敬请期待《MySQL 组复制》系列的其他文章^_^


文章转载自数据库不跑路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论