背景

  • 最近在进行 MySQL 集群搭建测试的研究中
    对于业界主流方案自然不能跳过
    在此,整理成完整的文章,希望道友能得到参考价值 …

★ PXC 集群介绍

  • PXC 是基于 Galera 协议的高可用集群方案
    可以实现多个节点间的数据同步复制以及读写,并且可保障数据库的服务高可用及数据强一致性

 

  • 环境
CentOS版本: CentOS Linux release 7.9.2009 (Core)
MySQL 版本: 5.7.32
PXC 版本 : 	percona/percona-xtradb-cluster 最新

前期准备

1). 三台 Vmware 虚拟机

在此,我以三台创建运行的 CentOS7 作为宿主机,进行配置操作演示

虚拟机 ip

端口

容器

数据卷

角色

192.168.80.221

9001

pn1

pnv1

Docker Swarm 管理节点,Master 节点

192.168.80.222

9001

pn2

pnv2

worker 节点

192.168.80.223

9001

pn3

pnv3

worker 节点

2). 开启四个 PXC 环境所涉及的端口:

3306:	# mysql 实例端口
4567:	# PXC cluster 相互通讯的端口
4444:	# 用于 SST(State Snapshot Transfer): 全量传输
4568:	# 用于 IST(Incremental state Transfer):增量传输传送
  • 以鄙人使用宝塔面板操作为例,注意以上端口的开启:

3). 部署前建议关闭 SELINUX、将 MySQL 数据库服务停止

安全增强型 Linux(Security-Enhanced Linux)SELinux

  • 一种方法【荐】,永久关闭 Selinux
    "vi /etc/selinux/config""SELINUX" 属性值设置成 disabled,然后 reboot 重启
  • 另一种方法,或者执行命令 Linux 临时关闭 Selinux: "setenforce 0"

4). 配置 ntp 服务,确保时间同步

[root@localhost ~]# yum -y install ntp ntpdate
 [root@localhost ~]# ntpdate 0.asia.pool.ntp.org
 [root@localhost ~]# hwclock --systohc
 [root@localhost ~]# date
 2021年 01月 08日 星期五 09:54:23 CST

5). 创建 Docker Swarm 集群

为了使三台服务器进行连接,如果没有安装 "docker",需要先执行命令: yum install -y docker

【拓展】:

  • 查看 docker 版本: docker -v 判断 docker 是否安装成功:docker docker 的启动/关闭/重启:service docker startservice docker stopservice docker restart
  • 然后,要在各个服务器中,开放所需的三个端口号
    (开放后重启 docker 服务 : service docker restart)
    2377用于集群管理通信的TCP端口4789用于容器覆盖网络7946用于容器网络发现
firewall-cmd --zone=public --add-port=2377/tcp --permanent
firewall-cmd --zone=public --add-port=4789/tcp --permanent
firewall-cmd --zone=public --add-port=4789/udp --permanent
firewall-cmd --zone=public --add-port=7946/tcp --permanent
firewall-cmd --zone=public --add-port=7946/udp --permanent
firewall-cmd --reload

docker根节点满了怎么办_docker

注意,以上的操作,要对三台虚拟机,全部进行配置哦!!!

选择一台服务器作为管理集群的服务器,此处,我选择的是 【192.168.80.221】

  • 运行命令:docker swarm init 则会得到一个形如下面的管理者口令
[root@localhost /]# docker swarm init
Swarm initialized: current node (g706owlgszx493xhpsb44k9t0) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-4ea65xsm8xsyhrmn42qg125b10dxtcmt80gnuijnnskddces2n-6fok68mg86nf5lkah1wnnj6ra \
    192.168.80.221:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
  • 然后在其他两个虚拟服务器中( 192.168.80.222192.168.80.223
    docker 服务启动的前提下
    都要执行上面的口令
  • docker根节点满了怎么办_docker_02

  • 查看 swarm 集群的所有节点
    只能在管理主机下【192.168.80.221】才能查看
docker node ls

docker根节点满了怎么办_docker根节点满了怎么办_03


【拓展】:

  • 如果要删除一个节点,执行命令为 :docker node rm -f [节点的ID] 如果要解散 swarm 集群
    先再 【manager 节点】上删除 所有 【worker 节点】
    再强制删除自己,执行:docker swarm leave -f 最后,还需要在各个 【worker 节点】主机上执行:docker swarm leave

6). 创建 Docker 虚拟网络,

  • 出于安全考虑,给 PXC 集群创建 Docker 内部虚拟网络,用于 PXC 集群独立使用
    此处我自定义的虚拟网络名称为:swarm_mysql
docker network create -d overlay --attachable swarm_mysql

【拓展】:

  • 查看虚拟网络: docker network inspect swarm_mysql 所有虚拟网络: docker network ls 删除虚拟网络: docker network rm swarm_mysql

docker根节点满了怎么办_PXC_04


搭建 PXC 集群

1). 下载 PXC 镜像 (三台主机都要做)

  • PXC 官方提供了 Docker 镜像,所以我们可以很方便的搭建 PXC 集群

Docker 仓库中的 PXC官方镜像:https://hub.docker.com/r/percona/percona-xtradb-cluster

  • 此处直接安装最新的 PXC 镜像
docker pull percona/percona-xtradb-cluster

建议配置一下加速镜像,请参考 【附录 - a: 配置 docker 加速镜像】

  • 重命名镜像名称 (名称太长,重命名一下)
docker tag percona/percona-xtradb-cluster pxc
  • 删除原始镜像
docker rmi percona/percona-xtradb-cluster

此时,可以通过命令查看所有的镜像:docker images

docker根节点满了怎么办_PXC_05


2). 创建分布式容器

注意: 第一个启动的 PXC节点是【主节点】,它要初始化 PXC 集群

PXC 启动之后,就没有【主节点】的角色了!此处只是随机选择了【192.168.80.221】,其实任意一个都可以!

鄙人设置的是以 "9001"端口访问 集群,所以记得开启端口(也可以选用 3306 等任意不冲突的端口!)

☞ 创建主节点容器 【192.168.80.221】

注意:在这一步之前,要把 MySQL 数据库停止服务 !

[root@localhost ~]# service mysqld status
 ERROR! MySQL is not running
  • 同时要记住:创建主节点之后,稍等一会儿才能连接(大概一两分钟)
    对于各参数的解释,请阅读 【附录 - b). 创建节点参数解释】
docker run -d --name=pn1 --net=swarm_mysql -p 9001:3306 -v pnv1:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=mT123456 -e CLUSTER_NAME=PXC1 -e XTRABACKUP_PASSWORD=mT123456 pxc

【补充知识点】:

  • 此处有必要提及一下,注意命令中的参数 "-v pnv1:/var/lib/mysql" 即:数据挂载在名称为 "pnv1" 的数据卷上,对应于宿主机的 "/var/lib/mysql" 路径
    通过命令:docker inspect pnv1
    可以找到数据卷位置,后期作为主节点的启动,是要知道这个路径的!
  • docker根节点满了怎么办_linux_06

  • 等待数据库启动完成 【自动执行,正常情况下会发现 MySQL 服务启动了!】

此时,可以查看虚拟网络 : docker network inspect swarm_mysql,会发现,主节点ip成功配置进去了:

docker根节点满了怎么办_PXC_07

【提示】:

  • 如果发现 MySQL 服务启动失败,建议先将容器停止,不然 MySQL 服务各种报错
    对节点的其他操作,请阅读 【附录 - c). 节点操作指令】
  • 此时,可以通过 Navicat 等数据库连接工具测试是否能够连接

    【提示】:
  • 通过我多次的配置测试发现,【主节点】配置基本不会有多少问题如果发现无法正常访问,那就查看下节点日志:docker logs [节点名] (注意其中出现的 "ERROR" 信息)
  • 而从第二个节点开始,基本根据不同的环境多少都会出现一些问题即便我根据大佬的视频操作,也是不可能一帆风顺!基本表现为,节点闪退、无法连接网上大部分经验像是大海捞针最好的方式就是,根据日志打印出的 "ERROR" 信息,在官网进行排查!!!
  • 注意,排查时,先 stop 节点运行不然,会出现更多的问题,比如你 MySQL后期直接不能用了 ...

☞ 创建从节点容器

必须主节点可以访问了,才能创建从节点,否则会闪退!

★ 加入第二个节点 【192.168.80.222】

相信,会有很多人在创建第二个节点时就会遇到问题,注意提示,要进行日志的排查: docker logs [节点名]

  • 我的创建节点命令如下:
docker run -d --name=pn2 --net=swarm_mysql -p 9001:3306 -v pnv2:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=mT123456 -e CLUSTER_NAME=PXC1 -e XTRABACKUP_PASSWORD=mT123456 -e CLUSTER_JOIN=pn1 pxc

注意:

  • 从第二个节点创建开始,需要增加 "-e CLUSTER_JOIN" 参数,表示与【主节点】容器同步
    此处的命令,与创建【主节点】不同的地方,也只有参数 --name(节点名)-v(数据卷),其他酌情自定义
  • docker根节点满了怎么办_docker_08

  • 稍等一两分钟
    可以查看节点状态:docker ps -a
  • docker根节点满了怎么办_docker根节点满了怎么办_09

  • 此时,可以继续通过 Navicat测试是否能够连接
  • docker根节点满了怎么办_linux_10

也可以查看虚拟网络情况,通过命令:docker network inspect swarm_mysql

★ 加入第三个节点 【192.168.80.223 】
  • 参考上面,则第三个节点创建命令为:
docker run -d --name=pn3 --net=swarm_mysql -p 9001:3306 -v pnv3:/var/lib/mysql --privileged -e MYSQL_ROOT_PASSWORD=mT123456 -e CLUSTER_NAME=PXC1 -e XTRABACKUP_PASSWORD=mT123456 -e CLUSTER_JOIN=pn1 pxc
  • 可以查看节点状态:docker ps -a
  • docker根节点满了怎么办_linux_11


其他操作,不做赘述!如果有更多的从节点需要创建,可以举一反三 …


3). 查看挂载情况

推荐的方式,需要进入 【主节点】的 mysql,运行查询语句:show status like 'wsrep%';

  • 鄙人测试发现,进入任意一个节点,都可以执行查询操作
    于是,我在节点2 [192.168.80.221] 的查询结果如下:
    可以看到 "wsrep_incoming_addresses" 的值就是我们三个容器的IP地址
    对于其他参数解释,建议可以参考 —— 【MySQL Galera cluster集群常用参数说明】
  • docker根节点满了怎么办_docker根节点满了怎么办_12


另外,我发现,在节点顺利启动后,可以通过查看虚拟网络信息,确认挂载情况

  • 操作命令:docker network inspect swarm_mysql
[root@localhost ~]# docker network inspect swarm_mysql
[
    {
        "Name": "swarm_mysql",
        "Id": "ir06z2hjlfduliphte8chwrop",
        "Created": "2021-01-14T15:46:33.522125189+08:00",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Containers": {
            "4d09f2b49a771f0976ea6379d1585059b1f54041ccdf975d540fc9e319258d3f": {
                "Name": "pn1",
                "EndpointID": "27662762e11842e96125cdca03a66941c7fe4c2574eea6a7cd29ed8a4b8cfea0",
                "MacAddress": "02:42:0a:00:00:02",
                "IPv4Address": "10.0.0.2/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.driver.overlay.vxlanid_list": "4097"
        },
        "Labels": {},
        "Peers": [
            {
                "Name": "localhost.localdomain-bedc99cf44f1",
                "IP": "192.168.80.221"
            },
            {
                "Name": "localhost.localdomain-986f2f07e8b7",
                "IP": "192.168.80.222"
            },
            {
                "Name": "localhost.localdomain-4a1e3925814d",
                "IP": "192.168.80.223"
            }
        ]
    }
]

4). 集群同步验证

验证是极为简单的,直接在任意节点数据库连接上,创建 db、创建数据表、操作数据

  • 然后,正常情况下,其他节点刷新后,会发现对应的数据同步变化!

【题外话】:


PXC 节点宕机以及重启操作

此处,推荐参考 —— 【MySQL 之 PXC 集群搭建:宕机操作】

知识点

  • 由于 PXC 在退出的时候会给集群中最后退出的那台打上标记,
    当集群重新启动的时候
    需要尽量先启动最后关闭的那台节点机器
    并且要按照主节点方式启动!

☞ 【从节点】操作

即,以 指定主节点 形式进入 PXC 集群创建的容器(理解起来即为【从节点】如:pn2、pn3)

如果主节点没有完全启动成功,从节点就会闪退

★ 如果指定的【主节点】正常运行中

直接运行指令: docker restart [节点名],数据会自行同步

★★ 如果指定的【主节点】也没有启动

此时,有两种可选择的方案

  • 第一种方案:先等【主节点】正常启动后,再执行 :docker restart [节点名]如果发现启动后闪退
    建议确认下数据卷中 "grastate.dat" 文件的 safe_to_bootstrap 参数为 0 再以 指定主节点方式 启动
  • 第二种方案:考虑以作为【主节点】的形式进行启动
    但是,要注意
    毕竟之前它的启动参数是以指定主节点方式来启动的
    所以,此时要有所变动
    修改数据卷中 "grastate.dat" 文件的 safe_to_bootstrap 参数为 1 再以 主节点方式 启动

☞【主节点】操作

即,以 自身为主节点

★ 如果所有节点都没有启动时

如果能确定,原来作为【主节点】的是最后一个离开集群的,可直接运行:docker restart [节点名]

  • 首先,
    可以确认一下:数据卷中 "grastate.dat" 文件的 safe_to_bootstrap 参数为 1然后,执行启动命令:docker start [节点名] 或者 docker restart [节点名] 等待查看第一个节点成功启动后,
    再按顺序,依次启动其他从节点:docker restart [节点名]

★★ 如果其他节点还在运行中

此时,要考虑使用指定主节点方式进行启动

  • 此时,可以删除自身容器 : docker stop [节点名]docker rm [节点名] 原来的数据卷无需删(继续使用,避免数据丢失)
    然后,确认一下:数据卷中 "grastate.dat" 文件的 safe_to_bootstrap 参数为 0 接着,再以从节点方式创建容器,加入集群(注意参数 "-e CLUSTER_JOIN" 的指定)

☞ 最坏情况,节点再创建一遍

  • 记不清之前的退出操作了,也懒得排查了
    先要保证不去删除数据卷(避免数据丢失)
    然后,这时,试着将所有的节点都 stoprm 操作
    再从创建节点步骤开始,执行一遍!

☞ 实际案例演示:

我在退出虚拟机时,习惯先关掉 从机

  • 第二天,重启电脑,打开虚拟机
    在其他虚拟机机都运行状态时
    先进 【主节点】
    找到数据卷位置:docker inspect [数据卷名] 然后,修改其目录下的 "gratate.dat" 文件中的 safe_to_bootstrap 参数为 1 接着执行命令:docker restart pn1
  • docker根节点满了怎么办_PXC_13


  • 等第一个节点服务器可以访问
    此时,进入第二个虚拟机的命令行中
    执行:docker restart pn2
  • 继续,进入后面的虚拟机命令行
    执行:docker restart pn3

至此,三个 PXC 节点都已启动,且数据同步


PXC 集群实际应用探讨

ThinkPHP5 上的使用

以鄙人常用的 ThinkPHP5 框架使用为例

  • 那么,在 "config/database.php" 中的配置参考如下:
//------------- PXC 集群配置参考----------------------------------
  'hostname'        => ['192.168.80.221','192.168.80.222','192.168.80.223'],
  'database'        => 'pxc_test',
  'username'        => 'root',
  'password'        => 'mT123456',
  'hostport'       =>  '9001',
  'deploy'          => 1,
//-------------------------------------------------------------

MyCat 部署读写分离

【提示】:

  • 在成熟的项目配置中,应该是考虑其他中间件来进行数据库分布式部署操作的
    比如,阿里开源的 MyCat 感兴趣的可以阅读下整理的文章
    —— 【CentOS7 下使用 MyCat 实现 MySQL 读写分离/主从切换】
  • 我在【192.168.80.221】主机上安装了 mycat 服务
    在此,附一张配置截图以作参考:
  • docker根节点满了怎么办_docker根节点满了怎么办_14

  • 如此一来
    上面项目配置中,就只会显示 mycat 连接信息(减少负载均衡配置中的代码冗余)
//------------- MyCat 主从分离配置参考----------------------------------
  'hostname'        => '192.168.80.221',
  'database'        => 'mycat_tp5_pro',
  'username'        => 'root_mycat',
  'password'        => 'mycat_007',
  'prefix'          => 'tp5_',//前缀而已,不要太在意
  'hostport'        => '8066',
//-------------------------------------------------------------

☞ 对比 “Replication” 集群部署

通常来讲,对于数据库集群部署,"PXC" 都会拿来与 "Replication" 进行对比!

docker根节点满了怎么办_docker_15

此处,引用前辈文章,以作知识共享咯 —— 【Docker 部署 Mysql 集群】

Replication 部署方案】:

docker根节点满了怎么办_PXC_16


PXC 部署方案】:

docker根节点满了怎么办_docker_17

注意,两种方案不是对立的,一个大型项目中,完全可以根据自己的业务 : 结合使用、取长补短


报错排查及解决

这只是我遇到的几个关键问题,酌情参考 …

1). “transport: x509: certificate has expired or is not yet valid”

[root@localhost ~]# yum -y install ntp ntpdate
 [root@localhost ~]# ntpdate 0.asia.pool.ntp.org
 [root@localhost ~]# hwclock --systohc
 [root@localhost ~]# date
 2021年 01月 08日 星期五 09:54:23 CST

2). “error:0407008A:rsa routines:RSA_padding_check_PKCS1_type_1:invalid padding”

当发现,节点无法连接后,这时就要查看日志

2021-01-14T09:02:35.487308Z 0 [ERROR] [MY-000000] [Galera] handshake with remote endpoint ssl://10.0.0.2:4567 failed: asio.ssl:67567754: 'invalid padding' ( 67567754: 'error:0407008A:rsa routines:RSA_padding_check_PKCS1_type_1:invalid padding')
This error is often caused by SSL issues. For more information, please see:
  https://per.co.na/pxc/encrypt_cluster_traffic
--------

重启节点,也可使用命令:docker restart [节点名称]


附录1. 知识拓展

a). 配置 docker 加速镜像

DockerDocker Hub 拉取镜像,因为是从国外获取,所以速度较慢

  • 编辑文件 daemon.json
vi /etc/docker/daemon.json
  • 在文件中输入以下内容并保存
{
  "registry-mirrors": ["http://hub-mirror.c.163.com","https://mirror.ccs.tencentyun.com","https://ung2thfc.mirror.aliyuncs.com"]
}
  • 重新加载配置信息及重启 Docker 服务
# 重新加载某个服务的配置文件
systemctl daemon-reload
# 重新启动 docker
service docker restart

b). 创建节点参数解释

命令

说明

-d

代表创建的容器在后台运行

–name=pn1

容器名称,自定义

–net=swarm_mysql

加入到 swarm_mysql的虚拟网络

-p 9000:3306

端口映射 宿主机端口:容器端口

-v pnv1:/var/lib/mysql

数据卷挂载在 "pnv1" 数据卷

可以理解为虚拟的磁盘,容器在保存数据的时候往 "/var/lib/mysql" 路径保存数据,其实就是把数据包存在数据卷上了

如果在这之前没有数据卷 pnv1,会自动创建一个进行挂载

–privileged

表示有读写权限

-e MYSQL_ROOT_PASSWORD=mT123456

Mysql 的 root 密码 (跟原来数据库设定的 root 密码没关系)

-e CLUSTER_NAME=PXC1

PXC 集群名称 (注意不要命为关键词:"PXC")

-e XTRABACKUP_PASSWORD=mT123456

PXC 集群之间数据同步的密码

-e CLUSTER_JOIN=pn1

表示与 pn1节点同步 (第一个节点是没有该参数的!

pxc

来自哪个镜像创建

c). 节点操作指令

感觉,用的还挺频繁的,比如节点配置错误,想换名字,删除数据卷时都会用到!

用途

指令

停止节点

docker stop [节点名]

重启节点

docker restart [节点名]

查看所有节点

docker ps

删除节点

docker rm [节点名]

查看日志

docker logs [节点名](建议用来排查错误)

d). 创建数据卷,用于之后挂载

注:PXC 容器只支持数据卷挂载方式,不支持目录挂载

docker根节点满了怎么办_mysql_19

  • 可以通过查看数据卷,以方便后期对数据及配置文件的查找:docker inspect [数据卷名]
[root@localhost download]# docker inspect pnv1
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/pnv1/_data", # 这里是在宿主机的保存位置
        "Name": "mTv1",
        "Options": {},
        "Scope": "local"
    }
]

文章

附录2. 搭建 Replication 集群

此处,补充 Docker 虚拟环境下,搭建 Replication 集群的方法,对比 PXC 集群

docker根节点满了怎么办_mysql_20

在此,我以三台创建运行的 CentOS7 作为宿主机,进行配置操作演示

虚拟机 ip

端口

容器

数据卷

角色

192.168.80.221

9002

rn1

rnv1

Docker Swarm 管理节点,Master 节点

192.168.80.222

9002

rn2

rnv2

Slave1 节点

192.168.80.223

9002

rn3

rnv3

Slave2 节点

1). 下载镜像 (三台主机都要做)

  • 此处直接安装第三方提供的的 Replication 镜像
docker pull mishamx/mysql
  • 重命名镜像名称 (名称太长,重命名一下)
docker tag mishamx/mysql rep
  • 删除原始镜像
docker rmi mishamx/mysql

此时,可以通过命令查看所有的镜像:docker images

docker根节点满了怎么办_mysql_21

2). 创建主节点容器 【192.168.80.221】

记住:创建主节点之后,稍等一会儿才能连接(大概一两分钟)

  • 创建命令如下:
    docker run -d --name=rn1 --net=swarm_mysql -p 9002:3306 -v rnv1:/var/lib/mysql --privileged -e MYSQL_MASTER_PORT=3306 -e MYSQL_ROOT_PASSWORD=mT123456 -e MYSQL_REPLICATION_USER=mozxx -e MYSQL_REPLICATION_PASSWORD=mozxx123 rep
  • 此时,可以通过 Navicat 等数据库连接工具测试是否能够连接
  • docker根节点满了怎么办_PXC_22

3). 创建从节点容器 【192.168.80.222】

从节点需要与主节点同步数据,没有主节点不能创建从节点

  • 创建节点命令如下:
    docker run -d --name=rn2 --net=swarm_mysql -p 9002:3306 -v rnv2:/var/lib/mysql --privileged -e MYSQL_MASTER_HOST=rn1 -e MYSQL_MASTER_PORT=3306 -e MYSQL_ROOT_PASSWORD=mT123456 -e MYSQL_REPLICATION_USER=mozxx -e MYSQL_REPLICATION_PASSWORD=mozxx123 rep

注意:

  • 创建从节点
    需要增加 "-e MYSQL_MASTER_HOST" 参数,表示指定的主节点

提示: 如果之前做了主从同步,建议先停掉: "stop slave;"

同理,第二个从节点,甚至更多的从节点创建命令都可参考如上 ...

4). 主从节点的宕机、启动问题

相比 PXC 集群的操作,Replication 集群操作极为简单

  • 从节点,退出或宕机后,直接 :docker restart [节点名] 并不影响其他节点的数据变化
  • 主节点,退出或宕机后
    唯一的表现就是,以它为主节点的其他从节点,数据都不变化了
    如果更改其他的数据,互不干扰
    启动时,直接 :docker restart [节点名] 之后,依然满足,主从配置效果 …