13

MySQL8.0 高可用集群化 · mysql-shell · mysql-router · docker · 单主多从 - Sol·wan...

 1 year ago
source link: https://www.cnblogs.com/Sol-wang/p/17122439.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

高可用集群的基本特点

负载均衡 / 读写分离 / 故障转移
本文以此为目标,利用 mysql-shell、mysql-router,基于 docker 的环境架构(篇幅太长,内容多了点儿)。

一、名词及要点

名词 解释
GR Group Replication;集群间的主从节点数据复制,利用 gtid、binlog 等确保所有节点数据的一致。
DDL Data Definition Language;操作库本身的语句。如 CREATE/ALTER/DROP等语句;自动提交当前事务;不能回滚。
DML Data Manipulation Language;针对数据的操作,如 CRUD,可回滚。

本文主要阐述内容:

    • 集群化配置项的作用说明
    • mysql-shell 组建管理集群
    • mysql-router 集群路由
    • 集群总体测试验证

二、环境说明

2.1 环境详细

名称 标签 角色
Rockylinux 9.1 本次整体测试虚拟机;可参考:https://rockylinux.org
mysql-shell 8.0.31 用来管理集群
mysql-router 8.0.31 集群路由服务
docker 20.10.22 集群服务容器载体
docker image:oraclelinux 9-slim 用来部署 mysql-router 的镜像
docker image:mysql 8.0.31 集群实例服务镜像
mysql-cli 8.0.31 用来测试验证连接的客户端

2.2 环境架构

    • Linux VM 中安装 mysql-shell
    • Linux VM 中安装 docker(运行3个mysql容器、一个mysql-router容器)
    • Linux VM 中安装 mysql-client

环境架构图示例

2320729-20230210174905313-718720046.png

应用安装层次图

MySQL集群 - 应用安装层次图

三、环境准备

- docker 的安装在这里省略。
- 网络地址全部使用 hostname 代替 IP 相互通信。
- 所有 MySQL 系相关的应用版本计划统一为 8.0.31。
- 所有 MySQL 涉及到的账号,为了测试便捷,以下都用 root / 统一密码操作。

3.1 docker 拉取所需的镜像

mysql image:利用官方提供的镜像,后续运行容器作为集群的节点

oraclelinux image:官方提供的系统镜像,后续为运行 mysql-router 的容器

# 拉取oraclelinux系统镜像
docker pull oraclelinux:9-slim
# 拉取MySQL官网提供的镜像
docker pull mysql:8.0.31
2320729-20230211171424679-1259526158.bmp

3.2 docker 创建集群专用网段

集群,当然建议固定 ip,甚至配置集群 hosts;这对于集群内部网络高并发下是很有必要的网络优化。

为此,这里单独创建一个虚拟网络,后续应用到集群中。(计划本次测试不涉及跨主机的网络转发)

# 这里创建一个名称为 br-mysql-clus 的自定义网络,计划集群所有节点处在同一网段下
docker network create --subnet=12.12.0.0/24 --gateway=12.12.0.254 br-mysql-clus
2320729-20230211171817062-1941292116.bmp

3.3 集群 hosts 设置

计划集群中的每个节点都用固定 IP,并指明 hostname,以 hostname 相互通信(这在集群中提升了通信的效率)。

计划所有的容器 hosts 文件都绑定到 Linux VM 的/etc/hosts;所以主机 hosts 设置所有节点的 IP > hostname:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# 追加集群各节点的 IP > hostname
# 以下定义,为后续容器的运行做准备
12.12.0.1       mc1    # mysql cluster node 1
12.12.0.2       mc2    # mysql cluster node 2
12.12.0.3       mc3    # mysql cluster node 3
12.12.0.5       mr     # mysql router

四、基于集群的 MySQL8 配置项说明

4.1 必须配置项

如果不配置以下各项,后续组建集群的 shell 会逐一列出不符合集群要求的项,并提醒完成必须的配置。

server_id:集群各节点唯一标识,必须为数字型;基于此配置会自动生成配置项 server_uuid 的值。

gtid_mode / dnforce_gtid_consistency:开启组复制 / 并保持事务的一致性,这个很重要。

group_replication_single_primary_mode:本次计划的 单主多从 集群模式。

binlog_transaction_dependency_tracking:集群同步数据时更精确的事务处理方式。

group_replication_group_name:统一的名称才可识别为属于同一个集群。

[mysqld]
# 各节点的唯一识别,各节点cnf唯一不同之处,只能是数字
server_id = 1
# 开启组复制的集群数据同步功能
gtid_mode = ON
enforce_gtid_consistency = ON
# 指明单主多从模式
loose-group_replication_single_primary_mode = ON
loose-binlog_transaction_dependency_tracking = WRITESET
# 集群名称,必为有效的UUID
loose-group_replication_group_name = "a53e2dec-a5fe-11ed-99b8-080027c5c3a3"

什么是 GTID

全局事务标识符;GTID 是创建的唯一标识符,基于事务的数据复制,可以识别和跟踪源服务器上提交的每个事务,在源和拓扑服务器上均唯一;它在源服务器上提交并由任何副本应用,源和副本之间始终保留GTID,只要在源上提交的所有事务也在副本上提交,在源上提交的事务只能在副本上应用一次,就可以保证两者之间的一致性。

4.2 需要关注的配置项

配置项说明解释:

group_replication_start_on_boot:节点加入集群时,自动开始复制 Master 数据功能,以保持节点间数据一致。

group_replication_bootstrap_group:集群启动后是否作为 Master 节点,自动开始RG;建议都设为 OFF。

group_replication_local_address:集群内各节点之间,当前节点对外的通讯地址。

group_replication_group_seeds:集群启动时,组建的基本节点。

[mysqld]
# 启动后自动运行组复制,默认=ON
#loose-group_replication_start_on_boot = ON

# 重启后的集群以哪个实例的数据为准的复制同步过程
#loose-group_replication_bootstrap_group = OFF

# 明确本节点的对外通信地址(不是必须,shell脚本可覆盖代替)
# 当 communication_stack = MYSQL 时,以下端口只能3306
# 当 communication_stack = XCOM 时,以下端口建议33061
#loose-group_replication_local_address="{host}:3306"

# 种子节点,由每个节点的通信地址组成(不是必须,shell脚本可覆盖代替)
#loose-group_replication_group_seeds="{host}:3306,{host}:3306,{host}:3306"

需要注意的配置项 group_replication_bootstrap_group

假设1:所有节点都设为 OFF,重启的集群不会自动开始组复制(GR)功能
假设2:多节点设为 ON,系统分不清以哪个节点为基准的组复制(GR)功能(脑裂现象)
假设3:固定一个节点设为 ON,此节点的数据在集群中不一定是最完整的

所以,重启后的集群,人为的选择 Master,手动启动组复制(GR)最为妥当

方案1:集群启动前,选好一台 ON 作为 Master,集群启动后,需改为 OFF
方案2:在被人为认定的 Master 主机上,手动启动GR,如下脚本:
  mysql> SET GLOBAL group_replication_bootstrap_group = ON;
  mysql> START GROUP_REPLICATION USER='***', PASSWORD='***';
  mysql> SET GLOBAL group_replication_bootstrap_group = OFF;

4.3 需要知道的配置项

以下默认值都已符合集群运行的基本要求,或者不同场景,您需要不同的配置。

log_bin:二进制日志,包括所有(DDL/DML)脚本的执行记录,用于实时主从数据同步/数据恢复。

log_replica_updates:同步过来的二进制更新日志,也需要记录到自己的二进制日志中;便于灾难时的恢复。

binlog_format:数据同步日志记录的程度;一般的/更细的/混合的;当然ROW更细的日志会带来更庞大的空间占用。

[mysqld]
#log_bin = ON                        # default = ON
#log_replica_updates = ON            # default = ON
#binlog_format = ROW                 # default = ROW
#master_info_repository = TABLE      # default = TABLE
#relay_log_info_repository = TABLE   # default = TABLE

什么是 binlog

Binary Log;以二进制的形式记录了对于数据库的变更过程。
binlog可设定单文件大小,过期时间等;多用于:数据恢复、主从同步。

binlog 的三种记录方式:
STATEMENT:能够记录大多数的脚本变更过程;
ROW:记录所有的脚本变更细节,空间占用过大;
MIXED:不同方式压缩记录所有脚本的变更,确保数据的一致性、准确性。

4.4 可适当调整的扩展配置项

[mysqld]
# 持久化设置,默认=NO
# 参数或配置保存起来,如:组建时产生的账户密码,重启后依然有效
#persisted_globals_load = ON

# 选举权重百分比,默认=50,正序排列优先顺序
#loose-group_replication_member_weight = 50

# 新版 默认=MYSQL,旧版默认=XCOM
# 各节点通讯端口不可随意使用:MYSQL必须用3306,XCOM可以用33061
# group_replication_communication_stack = MYSQL

# 事务写入算法方式(组复制默认的XXHASH64,<=8.0.1版本默认值为OFF)
#transaction_write_set_extraction = XXHASH64

# 设置群组白名单,包含在内的节点才能加入
#(旧版本CommunicationStack=XCOM时有效)
#loose-group_replication_ip_whitelist="192.168.1.0/24"

# 复制单位大小;默认 150000000 字节,可适当加大以提升复制效率
#loose-group_replication_transaction_size_limit = 1500000000

# 数据复制时,外键级联检测;本次测试不需要那么严谨,默认=OFF
#loose-group_replication_enforce_update_everywhere_checks = OFF

# 为创建 InnoDB Cluster,所要屏蔽的库表类型,默认值如下
#disabled_storage_engines = "MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"

以上 cnf 中绝大多数的配置项,在后续 shell 管理集群时,都会有对应的参数设置,以覆盖 cnf 原有配置

五、mysql-shell 组建 MySQL 集群

5.1 准备各节点配置文件

这里以[4.1 必须配置项]为模板,分别创建三个 cnf 配置文件:mc1.cnfmc2.cnfmc3.cnf

后续容器启动时,分别对应各自节点的 cnf 文件。各 cnf 唯一不同的配置项是server_id

5.2 docker 启动多个SQL实例容器

这里假设三个SQL实例(集群至少),用 docker container 启动运行起来。

运行容器为集群必要的绑定项

    • 指定计算机名
    • 指定固定 IP
    • 指定同一 hosts 文件(为确保 hostname 的识别)
    • 指定各节点的 cnf 配置文件

以下唯一不同的是:hostname、ip、container-name、cnf 项。

# 第一个SQL容器的启动
docker run -dit \
    --restart unless-stopped \        # 非人为宕机后自动重启
    -e LANG=C.utf8 \                  # 设定系统字符集
    -e TZ=Asia/Shanghai \             # 设定系统时区
    -e MYSQL_ROOT_PASSWORD=sa. \      # SQL实例 root 密码
    --network br.mysql.clus \         # 使用的网路名称(自定义创建的网络)
    --ip 12.12.0.1 \                  # 指定 IP,集群模式建议固定 IP
    --name mysql.clus.n1 \            # 容器名称
    --hostname mc1 \                  # 容器内计算机名称(用以集群内的节点通讯)
    -v /etc/hosts:/etc/hosts \        # 统一 hosts 配置
    -v /my/mc1.cnf:/etc/my.cnf \      # 各实例的配置文件
    mysql:8.0.31
# 第二个SQL容器的启动
docker run -dit \
    --restart unless-stopped \
    -e LANG=C.utf8 -e TZ=Asia/Shanghai \
    -e MYSQL_ROOT_PASSWORD=sa. \
    --network br.mysql.clus --ip 12.12.0.2 \
    --name mysql.clus.n2 --hostname mc2 \
    -v /etc/hosts:/etc/hosts \
    -v /my/mc2.cnf:/etc/my.cnf \
    mysql:8.0.31
# 第三个SQL容器的启动
docker run -dit \
    --restart unless-stopped \
    -e LANG=C.utf8 -e TZ=Asia/Shanghai \
    -e MYSQL_ROOT_PASSWORD=sa. \
    --network br.mysql.clus --ip 12.12.0.3 \
    --name mysql.clus.n3 --hostname mc3 \
    -v /etc/hosts:/etc/hosts \
    -v /my/mc3.cnf:/etc/my.cnf \
    mysql:8.0.31

记住以上三个容器的SQL镜像提供的环境变量 MYSQL_ROOT_PASSWORD,也就是给 SQL Instance 的 root 设置密码为 sa.;在后续的过程当中,都以 root 及这样的密码作为凭证。

集群三个节点容器运行效果,这里把各自节点容器名称分别为:
mysql.clus.n1
mysql.clus.n2
mysql.clus.n3

2320729-20230211173011088-1271707575.bmp

5.3 mysql-shell 介绍

作为集群节点的管理工具,安装在任意(Win/Linux)网络互通的系统都可以,这里用官网提供的 [MySQL Yum Repository] 的方式安装到 Linux VM

可参考官网:https://dev.mysql.com/doc/mysql-yum-repo-quick-guide/en/

# MySQL Yum Repository 安装到 Linux 系统中
dnf install https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm -y
dnf clean all && dnf makecache
# 在 Repository 中搜索以 mysql-shell 为前缀的应用
dnf list mysql-shell*
# 安装特定版本的 mysql-shell
dnf install -y mysql-shell-8.0.31

这里已经安装过,截图仅是搜索并安装的示例:

2320729-20230211180448341-575253218.bmp

安装完成后,进入 mysql-shell 命令行请输入:mysqlsh

2320729-20230213170957870-770624486.bmp

mysql-shell 提供了三种命令模式:JavaScript / python / sql;默认为 js 模式。

这里说明一下接下来常用到的 mysqlsh 命令:

全局对象 说明
dba 用于集群的管理
mysql SQL服务连接对象
shell 通用函数
os 与系统有关的操作
util 工具函数
shell 通用命令 说明
\? ; \help 获得帮助
\js ; \py ; \sql 切换模式
\ 多行命令
\c ; \connect {user}:{host}:{port} 连接到目标实例
\disconnect 断开连接会话
\reconnect 重新连接到会话
\! ; \system 执行系统脚本
\q ; \quit ; \exit 退出当前会话(mysql-shell)

在接下来的过程当中,经常会用:

\js 方式组建管理 MySQL 集群
\sql 方式查询目标实例的数据信息

5.4 MySQL AdminAPI

在 mysqlsh 中,使用 MySQL AdminAPI 提供的dba对象及函数来 检测节点/创建集群/配置集群/解散集群/重启集群 等的集群管理操作。

有关于 AdminAPI 的研究,可参考官方文档:https://dev.mysql.com/doc/mysql-shell/8.0/en/admin-api-userguide.html

接下来以dba对象为主的集群管理操作。

5.5 检测节点实例

前期,已经运行了三个MySQL容器,参考[5.2 docker 启动多个SQL实例容器],并且配置了运行集群的必要参数;但在创建集群前,通常都会检验目标实例是否符合加入集群的要求:

先连接任意一个 Instance,比如:\c root@mc1:3306(还记得 root 密码么,也许会让你输入凭证)

然后检测所有节点的配置,是否符合集群的基本运行条件(各 cnf 的必须配置项,未配好的会提醒):

# 分别检测各节点(还记得先前配置的 hosts 各名称么)
dba.checkInstanceConfiguration('root@mc1:3306');
dba.checkInstanceConfiguration('root@mc2:3306');
dba.checkInstanceConfiguration('root@mc3:3306');

过程如下截图示例:

2320729-20230211190747142-218977225.bmp

如果检测失败

1、可用 \c 方式连接到目标实例后
2、再用 dba.configureLocalInstance(); 方法引导完成必须的配置

5.6 创建集群

# 在任意目标实例中,创建名为 clus-1 的集群
# 那么,当前实例会被作为 Master 角色存在
var clus = dba.createCluster('clus-1');
# 或者,也可以指定目标实例名称,创建集群
# 如:dba.createCluster('clus-1',{localAddress:'root@mc2:3306'});
# 还记得名为 group_replication_local_address 的配置参数么,所以以上 localAddress 的值会覆盖此参数值
#
# 集群创建完成后,可用 status(); 函数查看当前集群状态信息
clus.status();
#
# 也可以获取当前节点所处的集群
var clus1 = dba.getCluster();
mysql-shell 创建集群 并查看集群状态

从上图可以看出:此节点为集群的主节点、可读可写、单主多从模式、集群内部通讯地址为 mc1:3306。

5.7 加入新节点

加入节点,需要设定数据恢复(与主节点保持一致)的方式:克隆、增量、自动。

可以加参数指明方式;也可以在新增过程中按系统提示选择。

# 加入新的集群节点,过程中通常选择 Clone 模式来复制主节点的数据
clus.addInstance('root@mc2:3306');
clus.addInstance('root@mc3:3306');
# 当然也有提醒信息;
# 比如:clus.addInstance('root@mc2:3306',{localAddress:'root@mc2:3306'});
# 追加的 localAddress 参数,更明确的指出此节点对集群的通讯地址
# 所以也可省略的参数,mysqlsh 也可自动取实例 Uri 作为 localAddress 参数值
#
# 此时再 .status() 查看集群状态
clus.status();

集群添加新节点图例:

2320729-20230213121556540-1647435938.bmp

集群 .status() 状态信息图例:

2320729-20230213121359181-268081717.bmp

... ... 加入更多的节点;单主多从的集群创建完成。

节点自动连接到集群

当因为连接超时或性能压力等,被自动踢出集群的节点,恢复后自动连接到集群;
或人为修复故障后,可以手动通过 rejoinInstance() 函数再次连接到集群中;
被 removeInstance() 的节点恢复正常后,通过 addInstance() 再次加入集群。

5.8 常用集群管理函数

全局函数 说明
dba.configureLocalInstance(); 配置当前节点为符合集群的要求,不符合的配置项会自动提示。
dba.checkInstanceState({Uri}); 检查节点配置,列出节点的当前具体情况(冲突/分歧/错误)。
dba.configureInstance({Uri}, { option:value }); 配置远程SQL实例节点参数。
dba.checkInstanceConfiguration({Uri}); 检查指定节点是否符合加入集群的要求。
dba.createCluster({cluster-name}); 以指定(默认:当前)节点上下文为基准,创建一个集群。
dba.getCluster({cluster-name}); 取得当前节点所处/参数指定的集群对象。
dba.rebootClusterFromCompleteOutage({cluster-name}); 重启指定的集群(建议先 check 各节点)
dba.dropMetadataSchema(); 删除整个 Schema(无法恢复)。
当前集群对象函数 说明
{cluster}.addInstance({Uri}); 集群加入新节点。
{cluster}.status(); 集群状态信息。
{cluster}.describe(); 集群结构信息。
{cluster}.removeInstance({Uri}); 集群内移除指定的节点实例。
{cluster}.rescan(); (属于集群)列出未运行在集群内的节点实例。
{cluster}.rejoinInstance({Uri}); (故障节点修复后)重新连接到集群。
{cluster}.foreQuorumUsingPartitionOf({Uri}); 恢复集群(建议先 check 各节点)
{cluster}.dissolve(); 解散集群(各节点数据保持现状)。
{cluster}.help({fun-name}); 帮助;所有函数 或 指定函数。
{cluster}.options(); 列出此集群可配参数。
{cluster}.setOption({option}, {value}); 为此集群设定配置项。
{cluster}.setInstanceOption({Uri}, { option:value }); 为此集群的指定节点实例,设定配置项。
{cluster}.listRouters(); 查看路由信息
{cluster}.setupAdminAccount({account-name}); 为集群中的所有节点统一创建相同的账户高权限及密码(替代root)。
{cluster}.setupRouterAccount({account-name}); 为集群中的路由统一创建相同的账户高权限及密码(替代root)。

函数应用场景案例:重启集群

可能预先要做的准备工作:在集群中寻找数据集更接近完善的节点,以作为 Master 节点。

    • 生成集群节点报告,从中做出最佳选择:dba.rebootClusterFromCompleteOutage({ dryRun : true });
    • 依次连接到每个SQL实例,并执行脚本后对比GTID事务量:show variables like '%gtid_executed%';

参数应用场景案例:节点异常时踢出集群前的延迟时长

当某个节点异常时,系统会有5秒的检测时长,之后还会有延迟时长,后踢出集群;为了防止被误踢,延迟时长可配。

    • 比如在首次加入集群时设定参数:{cluster}.addInstance({Uri},{ expelTimeout : 8 });
    • 再比如非首次的后续设定方式:{cluster}.setInstanceOption({Uri},{expelTimeout:8});

那,,,mysql-shell 管理的集群有哪些参数可以设定的呢?

{cluster}.options();函数列出每个节点的所有可设置参数:(截取部分)

2320729-20230213121818858-1557154811.bmp

有没有熟悉的参数。。。

这里 options 所有的参数都与 cnf 配置文件参数一一对应;

比如:可以用dba.createCluster('{Uri}',{ key:value, key:value ... });这样的方式附带参数

比如:可以用.addInstance('{Uri}',{ key:value, key:value ... });这样的方式附带参数

也可以用函数.setOption( option, value );这样的方式完成参数设定。

用 mysql-shell 管理集群时,默认情况下,以上都可覆盖原有(my.cnf)配置,并可持久化(my-auto.cnf)保存。

六、集群 GR 测试

6.1 GR 数据同步测试

测试场景:在 Master 节点创建库/表/数据后;查看 Slave 节点是否已同步数据。

# 在 Master 节点创建库/表/数据
\c root@mc1:3306
create database clusterdb;
create table clusterdb.emp(id bigint not null AUTO_INCREMENT,usercode VARCHAR(32) DEFAULT NULL,createtime datetime default now(),PRIMARY KEY (id));
insert into clusterdb.emp(usercode) values ('Sol'),('wang');
# 查看 Slave 节点是否已同步数据
\c root@mc2:3306
select * from clusterdb.emp;

测试结果图:主从数据同步完成。

2320729-20230213120400291-1441682958.bmp

6.2 故障转移测试

测试场景:Master 节点制造宕机(停机),集群选举出新的 Master 节点,是否完成故障转移。

1、假设的 Master 宕机:docker stop mysql.clus.n1
2、再查看集群 Master 角色所处节点。

# 连接到集群节点
mysqlsh --uri root@mc2:3306
# 查看集群节点状况
dba.getCluster().status();
2320729-20230213120706174-214856579.bmp

测试结果上图:其中 mc2:3306 节点已接替 Master 角色,完成故障转移。

七、创建 mysql-router 容器加入集群

docker mysql-router 镜像,官网有测试版,参考:https://hub.docker.com/r/mysql/mysql-router

既然非生产环境的稳定版,这里在容器中安装 mysql-router。

7.1 容器中部署 mysql-router

运行已有的 oraclelinux 镜像,并进入容器:

# oraclelinux 镜像运行出新容器
docker run -dit --restart unless-stopped -e LANG=C.utf8 -e TZ=Asia/Shanghai \
    --name mysql.clus.mr --hostname mr \
    --network br.mysql.clus --ip 12.12.0.5 \
    -p 6446:6446 -p 6447:6447 \
    -v /etc/hosts:/etc/hosts \
    oraclelinux:9-slim
# 进入容器
docker exec -it mysql.clus.mr bash

容器内安装 mysql-router

通常:docker 镜像的系统,只提供最基本的应用功能,最大程度的简化,是 docker image 的特点之一。
所以:以下镜像的容器内,yum/dnf 已被移除,rpm 也被简化,但仅提供了最简陋的应用安装方式 microdnf。
当然:也可以通过 microdnf 来安装上功能强大的 yum/dnf 等,以下继续使用 microdnf 方式安装应用。

# 这里使用官方提供的 Yum Repository 方式安装
curl -#O https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm
rpm -ivh mysql80-community-release-el9-1.noarch.rpm
# 作为镜像的微型系统,当然是仅提供基本功能
# yum/dnf 都没了,当然也可以安装上,这里使用自带的 microdnf 命令安装
# 更新 Repos,为了后续更快的应用安装(多等会)
microdnf clean all && microdnf makecache
# 模糊搜索以 mysql-router 为前缀的安装包
microdnf repoquery mysql-router*
# 搜索到的包,安装指定版本;格式:{name}-{版本号}
microdnf install mysql-router-community-8.0.31 -y
# 查看安装效果
mysqlrouter -V

7.2 容器内启动 mysql-router

# 命令有多种可选参数,这里用以下方式初始化 mysql-router 实例
# 集群 Master主机的URI格式:{sql-user}:{pass}@{host}:{port}
mysqlrouter --bootstrap root:sa.@mc1:3306 --user=root --force
# 初始化后产生的配置文件可查看,或修改配置项
cat /etc/mysqlrouter/mysqlrouter.conf
# 启动后台运行实例
mysqlrouter --user=root &

7.3 或制作成 mysql-router 镜像

a、创建空文件夹,作为制作镜像的根目录;

b、文件夹中创建 Dockerfile 文件:touch Dockerfile

  Dockerfile 文件内容如下:

# 基于 Oracle 9 Linux 系统的依赖
FROM oraclelinux:9-slim
# 系统默认字符集
ENV LANG C.utf8
# 系统默认时区
ENV TZ Asia/Shanghai
# mysql-router 用到的集群 Master Uri 作为系统变量
# 集群 Master Uri 格式为:{user}:{pass}@{host}:{port}
ENV MASTER_URI root:sa.@mc1:3306
# 以下运行在指定账户下
USER root
# 进入系统后的默认目录
WORKDIR ~
# 制作系统所需的命令步骤
# - 网络安装MySQL官网提供的 Yum Repository,编译 mysql-router 在此 Repo 下安装
RUN rpm -ivh https://repo.mysql.com/mysql80-community-release-el9-1.noarch.rpm
RUN microdnf clean all
RUN microdnf makecache
RUN microdnf install mysql-router-community-8.0.31 -y
RUN mysqlrouter --bootstrap $MASTER_URI -u=root --force
# 对外提供 mysql-router 的读写端口
EXPOSE 6446 6447
# mysql-router 初始化 并 启动
ENTRYPOINT mysqlrouter -u=root

c、Dockerfile 文件保存退出后,在此目录下执行 build 命令,生成 image 包。

# build 格式:docker build -t {image-name}:{tag} {根目录}
docker build -t mysql/router8:1.0 .
# 查看 image list
docker image ls
2320729-20230213173954237-922153325.bmp

将制作的 mysql/router8 镜像运行到容器

docker run -dit \
    --restart unless-stopped \            # 非手动关机时自动重启
    --name mysql.clus.mr \                # 容器名称
    --hostname mr \                       # 计算机名
    --network br.mysql.clus \             # 指定网络
    --ip 12.12.0.5 \                      # 集群时建议使用固定IP
    -p 6446:6446 -p 6447:6447 \           # 对外开发的端口映射
    -v /my/mr.hosts:/etc/hosts \          # 集群时的 hosts 优化
    -e MASTER_URI=root:sa.@mc2:3306 \     # 集群 Master uri 地址
    mysql/router8:1.0                     # 使用制作的镜像

实例节点 + 路由 的容器列表:

2320729-20230213180618619-813257842.bmp

集群查看路由信息:listRouters()

2320729-20230214174037326-290882464.bmp

所以,,,客户端在连接的时候,不同的动作连接对应的端口号。

八、集群路由测试

首先,客户端 mysql-cli 先连接到 mysql-router;

mysql-router 按集群状况,把读写动作连接到不同的集群节点上。

8.1 基于路由的 - 读写分离

8.1.1 写入端口 6446 测试

测试办法:客户端 mysql-cli 连接 mysql-router 的写入端口 6446,是否连接到 Master?

# mysql-cli 连接到 mysql-router
mysql -h mr -u root -P 6446 -p
# - 验证连接的主机(是不是 mc1)
select @@hostname, @@port;
2320729-20230213183404931-1374639140.bmp

上图测试结果显示:路由的 6446 端口连接到 Master,并可写入数据;测试通过。

8.1.2 只读端口 6447 测试

测试办法:客户端 mysql-cli 连接 mysql-router 的只读端口 6447,是否连接到 Slave?

# mysql-cli 连接到 mysql-router
mysql -h mr -u router_newuser_1 -P 6447 -p
# - 验证连接的主机(是不是 mc2,mc3)
select @@hostname, @@port;
# - 验证数据是否已经同步到从机
select * from emp;
2320729-20230213184753466-1491649815.bmp

上图测试结果显示:路由的 6447 端口,连接到了 Slave 节点,并可查询数据;测试通过。

8.3 基于路由的 - 负载均衡

测试场景:透过路由 6447 只读端口,多次连接查询数据,是否轮询连接到不同的只读节点?

2320729-20230213190741994-442759210.bmp

上图测试结果显示:多次连接只读端口,连接到了不同的只读节点;测试通过。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK