背景
- 最近在进行
MySQL
集群搭建测试的研究中
对于业界主流方案自然不能跳过
在此,整理成完整的文章,希望道友能得到参考价值 … - 对于
docker
不熟悉的小伙伴,个人建议移步文章 ——【CentOS7 下 PXC 集群部署操作指导】
【注】:Percona XtraDB Cluster(简称 PXC 集群)
—— 业界主流的MySQL
集群方案
★ PXC 集群介绍
PXC
是基于Galera
协议的高可用集群方案
可以实现多个节点间的数据同步复制以及读写,并且可保障数据库的服务高可用及数据强一致性
PXC
最大的优势:强一致性、无同步延迟 (牺牲性能)
介绍不做赘述,可参考 ——
【MySQL 高可用方案-PXC 环境部署记录】
- 环境
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 start
、service docker stop
、service 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
注意,以上的操作,要对三台虚拟机,全部进行配置哦!!!
选择一台服务器作为管理集群的服务器,此处,我选择的是
【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.222
、192.168.80.223
)
在docker
服务启动的前提下
都要执行上面的口令查看
swarm
集群的所有节点
只能在管理主机下【192.168.80.221】
才能查看
docker node ls
【拓展】:
- 如果要删除一个节点,执行命令为 :
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
搭建 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
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
可以找到数据卷位置,后期作为主节点的启动,是要知道这个路径的!等待数据库启动完成 【自动执行,正常情况下会发现
MySQL
服务启动了!】
此时,可以查看虚拟网络 :
docker network inspect swarm_mysql
,会发现,主节点ip
成功配置进去了:
【提示】:
如果发现
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 ps -a
此时,可以继续通过
Navicat
测试是否能够连接
也可以查看虚拟网络情况,通过命令:
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
其他操作,不做赘述!如果有更多的从节点需要创建,可以举一反三 …
3). 查看挂载情况
推荐的方式,需要进入
【主节点】
的 mysql,运行查询语句:show status like 'wsrep%';
- 鄙人测试发现,进入任意一个节点,都可以执行查询操作
于是,我在节点2[192.168.80.221]
的查询结果如下:
可以看到"wsrep_incoming_addresses"
的值就是我们三个容器的IP地址
对于其他参数解释,建议可以参考 ——【MySQL Galera cluster集群常用参数说明】
另外,我发现,在节点顺利启动后,可以通过查看虚拟网络信息,确认挂载情况
- 操作命令:
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、创建数据表、操作数据
- 然后,正常情况下,其他节点刷新后,会发现对应的数据同步变化!
【题外话】:
- 个人感觉,
最终成果跟以前配置的MySQL
数据库主从同步没啥大的区别
只是没有了主从之分
那就相当于所有节点【互为主备】
对比参考 ——【CentOS7 下 MySQL5.7.32 主从复制+同步配置操作 (一主多从+多主多从)】
PXC 节点宕机以及重启操作
此处,推荐参考 ——
【MySQL 之 PXC 集群搭建:宕机操作】
知识点
- 由于
PXC
在退出的时候会给集群中最后退出的那台打上标记,
当集群重新启动的时候
需要尽量先启动最后关闭的那台节点机器
并且要按照主节点方式启动!
☞ 【从节点】操作
即,以
指定主节点
形式进入PXC
集群创建的容器(理解起来即为【从节点】如:pn2、pn3)
如果主节点没有完全启动成功,从节点就会闪退
★ 如果指定的【主节点】正常运行中
直接运行指令:
docker restart [节点名]
,数据会自行同步
★★ 如果指定的【主节点】也没有启动
此时,有两种可选择的方案
第一种方案:先等【主节点】正常启动后,再执行 :
docker restart [节点名]
如果发现启动后闪退
建议确认下数据卷中"grastate.dat"
文件的safe_to_bootstrap
参数为0
再以 指定主节点方式 启动第二种方案:考虑以作为【主节点】的形式进行启动
但是,要注意
毕竟之前它的启动参数是以指定主节点方式来启动的
所以,此时要有所变动
修改数据卷中"grastate.dat"
文件的safe_to_bootstrap
参数为1
再以 主节点方式 启动
☞【主节点】操作
即,以
自身为主节点
启动的容器(理解起来即为【主节点】,如 : pn1)
★ 如果所有节点都没有启动时
如果能确定,原来作为【主节点】的是最后一个离开集群的,可直接运行: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"
的指定)
☞ 最坏情况,节点再创建一遍
- 记不清之前的退出操作了,也懒得排查了
先要保证不去删除数据卷(避免数据丢失)
然后,这时,试着将所有的节点都stop
,rm
操作
再从创建节点步骤开始,执行一遍!
☞ 实际案例演示:
我在退出虚拟机时,习惯先关掉 从机
- 第二天,重启电脑,打开虚拟机
在其他虚拟机机都运行状态时
先进 【主节点】
找到数据卷位置:docker inspect [数据卷名]
然后,修改其目录下的"gratate.dat"
文件中的safe_to_bootstrap
参数为1
接着执行命令:docker restart pn1
- 等第一个节点服务器可以访问
此时,进入第二个虚拟机的命令行中
执行: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
服务
在此,附一张配置截图以作参考:如此一来
上面项目配置中,就只会显示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 部署 Mysql 集群】
【Replication
部署方案】:
【PXC
部署方案】:
注意,两种方案不是对立的,一个大型项目中,完全可以根据自己的业务 :
结合使用、取长补短
!
报错排查及解决
这只是我遇到的几个关键问题,酌情参考 …
1). “transport: x509: certificate has expired or is not yet valid”
- 服务器间的时间不同步,参考文章:【CentOS7 时间与网络时间同步】
[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
--------
- 通过对
"ERROR"
信息的阅读
建议阅读文章链接:https://per.co.na/pxc/encrypt_cluster_traffic
于是在官方文档中注意到一个提示信息:
重启节点,也可使用命令:
docker restart [节点名称]
附录1. 知识拓展
a). 配置 docker
加速镜像
Docker
从Docker 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). 创建节点参数解释
- 文档 ——
【Docker run 命令】
命令 | 说明 |
---|---|
-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 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
集群
在此,我以三台创建运行的
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
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
等数据库连接工具测试是否能够连接
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 [节点名]
之后,依然满足,主从配置效果 …
提示
当前这种部署方式,不支持互为主备的效果
虽然配置简单
但是,毕竟存在着重要的同步延迟
问题
需要跟PXC
集群取长补短原生配置方式,请参考 ——
【CentOS7 下 MySQL5.7.32 主从复制+同步配置操作 (一主多从+多主多从)】
对于
MySQL
配置参数的修改,需要注意一下,可参考 ——【Docker 中,对 mysql 配置文件的修改操作】