Docker 通过PXC+Nginx实现高可用强一致性的mysql集群(单机多节点)
1.基础软件
本人的构建环境如下:
- Ctenos7
- Docker version 20.10.21, build baeda1f
2.基础原理
- 数据同步时双向的,任何一个mysql节点写入数据,都会同步到集群中其它的节点。
- 同步复制,事务在所有集群节点要么同时提交,要么同时不提交
上图为PXC方案,支持各个节点都可以独写
上图为同步方案,任何数据都是同步复制,同时提交,要么同时不提交
3.安装PXC镜像
#拉取pxc镜像
docker pull percona/percona-xtradb-cluster:5.7.30
#此次指定版本,8.0后需要配置证书
#修改镜像名称
docker tag percona/percona-xtradb-cluster:5.7.30 pxc
#删除镜像
docker rmi percona/percona-xtradb-cluster:5.7.30
#查看镜像
docker images
4.创建内部网络
出于安全考虑,需要给 PXC 集群实例创建 Docker内部网络
#创建内部网段,24位,名称pxc-network:
docker network create --subnet=172.30.0.0/24 pxc-network
#注意:不能和宿主机网络一致
#查看pxc-network网段
docker inspect pxc-network
#删除pxc-network(这里不执行,参考)
docker network rm pxc-network
5.创建docker数据卷
注意:pxc不支持映射目录,所以采样映射数据卷的方式
Docker 卷是容器中的 PXC 节点映射数据目录的解決办法
一旦创建出docker容器,尽量不要把业务数据存在容器内,因为出问题的话数据可能就找不到了。 可以把业务数据保存在宿主机内,通过映射技术将宿主机上的目录映射到容器内。在运行容器的时候,把业务数据保存在映射目录里,也就是存储到宿主机上面。如果容器出什么问题,可以在创建一个容器,再将目录映射给该容器,则业务数据就导入了
#创建数据卷 v1 v2 v3 v4 v5
docker volume create v1
docker volume create v2
docker volume create v3
docker volume create v4
docker volume create v5
#查看数据卷
docker inspect v1
#删除数据卷
docker volume rm v1
6.创建pxc容器
开始创建5个MySQL节点
命令参数说明:端口3306,密码123456,集群名称PXC,同步数据密码123456,映射数据目录到宿主机的v1数据卷,给予最高权限,名称叫node1,网段为pxc-network,ip指定为172.30.0.2,运行的镜像是pxc。
6.1第一个节点
docker run -d -p 3301:3306 -e MYSQL_ROOT_PASSWORD=test.888 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=test.888 -v v1:/var/lib/mysql --privileged --name=pxc-node1 --net=pxc-network --ip 172.30.0.2 pxc
注意:第一个节点启动比较慢,需要等待1分钟时间,可以使用数据据连接工具连接
6.2第2,3,4,5个节点
docker run -d -p 3302:3306 -e MYSQL_ROOT_PASSWORD=test.888 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=test.888 -e CLUSTER_JOIN=pxc-node1 -v v2:/var/lib/mysql --privileged --name=pxc-node2 --net=pxc-network --ip 172.30.0.3 pxc
docker run -d -p 3303:3306 -e MYSQL_ROOT_PASSWORD=test.888 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=test.888 -e CLUSTER_JOIN=pxc-node1 -v v3:/var/lib/mysql --privileged --name=pxc-node3 --net=pxc-network --ip 172.30.0.4 pxc
docker run -d -p 3304:3306 -e MYSQL_ROOT_PASSWORD=test.888 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=test.888 -e CLUSTER_JOIN=pxc-node1 -v v4:/var/lib/mysql --privileged --name=pxc-node4 --net=pxc-network --ip 172.30.0.5 pxc
docker run -d -p 3305:3306 -e MYSQL_ROOT_PASSWORD=test.888 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=test.888 -e CLUSTER_JOIN=pxc-node1 -v v5:/var/lib/mysql --privileged --name=pxc-node5 --net=pxc-network --ip 172.30.0.6 pxc
7.验证PXC集群
可以使用navicat连接3301/3302/3303/3304/3305的数据库
可以再3301先建数据库testdb1,并新建user表,发现3302/3303/3304/3305 数据库都同步成功了
同步成功!
8.数据库负载均衡
虽然搭建了集群,但是不使用数据库负载均衡,单节点处理所有请求,负载高,性能差
将请求均匀地发送给集群中的每一个节点。
- 所有请求发送给单一节点,其负载过高,性能很低,而其他节点却很空闲。
- 使用nginx或者Haproxy做负载均衡,可以将请求均匀地发送给每个节点,单节点负载低,性能好
负载均衡首先是数据库的集群,加入5个集群,每次请求都是第一个的话,有可能第一个数据库就挂掉了,所以更优的方案是对不同的节点都进行请求,这就需要有中间件进行转发,比较好的中间件有nginx,haproxy等。
nginx作为负载均衡的中间件
#tcp/ip
stream{
#mysql 负载均衡
upstream mysql{
server 100.100.200.213:3301 weight=1;
server 100.100.200.213:3302 weight=1;
server 100.100.200.213:3303 weight=1;
}
server {
listen 3306;
proxy_pass mysql;
}
}
9.程序连接
#此处的端口就是nginx对外映射的端口 3306
他会随机分配到几个节点去查询数据
username: root
password: test.888
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://100.100.200.213:3306/ecdb?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
10.热备份数据
冷备份
- 冷备份是关闭数据库时候的备份方式,通常做法是拷贝数据文件
- 是简单安全的一种备份方式,不能在数据库运行时备份。
- 大型网站无法做到关闭业务备份数据,所以冷备份不是最佳选择
热备份
- 热备份是在系统运行状态下备份数据
MySQL常见的热备份有LVM和XtraBackup两种方案
- LVM:linux的分区备份命令,可以备份任何数据库;但是会对数据库加锁,只能读取;而且命令复杂
- XtraBackup:不需要锁表,而且免费
XtraBackup
XtraBackup是一款基于InnoDB的在线热备工具,具有开源免费,支持在线热备,占用磁盘空间小,能够非常快速地备份与恢复mysql数据库
- 备份过程中不锁表,快速可靠
- 备份过程中不会打断正在执行地事务
- 备份数据经过压缩,占用磁盘空间小
全量备份和增量备份
- 全量备份:备份全部数据。备份过程时间长,占用空间大。第一次备份要使用全量备份
- 增量备份: 只备份变化的那部分数据。备份的时间短,占用空间小。第二次以后使用增量备份
#PXC全量备份
#备份要在某个PXC节点的容器内进行,但应该把备份数据保存到宿主机内。所以采用目录映射技术。
先新建Docker卷:
docker volume create backup
#挑选一个PXC节点pxc-node1,将其容器停止并删除,然后重新创建一个增加了backup目录映射的node1容器
#注意:由于PXC各个节点数据节点都是一致的,所以只需要进入一个节点进行备份就行了。
docker stop pxc-node1
docker rm pxc-node1# 数据库数据保存在Docker卷v1中,不会丢失
# 参数改变:
# 1. -e CLUSTER_JOIN=pxc-node2;原来其他节点是通过node1加入集群的,现在node1重新创建,需要选择一个其他节点加入集群
# 2. -v backup:/data;将Docker卷backup映射到容器的/data目录
docker run -d -p 3301:3306 -e MYSQL_ROOT_PASSWORD=test.888 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=test.888 -v v1:/var/lib/mysql -v backup:/data -e CLUSTER_JOIN=pxc-node2 --net=pxc-network --privileged --ip 172.30.0.2 --name=pxc-node1 pxc
#进入pxc-node1节点
#进入节点
docker exec -it pxc-node1 /bin/bash
#更新update
yum update
#注意:会提示没有权限(这代表进入这个node1服务中的时候没有权限操作,所以我们要给到root用户进入服务)
#退出当前服务
ctrl+d
#重新以root角色进入docker服务,随便进入一个节点,这里我进入node1
docker exec -it -u 0 pxc-node1 /bin/bash
#执行update更新
yum update
#安装xtrabackup
yum install percona-xtrabackup-24
#安装完后进行全量备份:
innobackupex --user=root --password=MySQL密码 /data/backup/full
#执行完后自动开始全量备份
#切换到全量备份文件夹
cd /data/backup/full
#查看
ls
#=====================================================
#退出docker服务,由于有目录映射,所以宿主机上也会看到文件,具体方法:
#查看宿主机备份的数据目录在哪:
docker inspect backup
#切换到该文件夹
cd /var/lib/docker/volumes/backup/_data
#查看
ls
发现有backup目录,进入backup目录里面的full目录中查看,发现有全量备份文件
11.冷还原
MySQL的数据还原方式不像备份一样,MySQL数据还原只有冷还原,docker服务和单机节点差异是,docker还原的时候需要把docker的PXC集群解散掉,删除各个节点,之后新建一个新的节点并 进行冷还原,最后新建其他节点和当前节点进行数据同步;
docker stop #掉各个节点
docker rm #删掉各个节点
docker volume rm #删掉各个数据卷,这里删掉的是pxc服务的数据卷不是backup备份文件数据卷,千万别用删除孤卷命令,因为解散pxc后backup卷也是孤卷了,删除孤卷命令会把备份数据也删掉了
新建一个新节点,命令和搭建pxc集群一致
#进入该节点
docker exec -it -u 0 node1 bash
#安装xtrabackup
#执行MySQL数据清空指令
rm -rf /var/lib/mysql/*
#执行还原命令
innodackupex --user=root --password=密码 --apply-back /data/backup/full/备份文件名/
这里的--apply-back参数指的是回滚掉全量备份之间产生的事务差异数据
12.定时备份
crontab 计划任务
#
crontab -e
#添加计划任务
00 02 * * * /var/lib/mysql/backup.sh
#crontab 计划任务在添加或修改后,需要保存并重启服务才能生效
systemctl restart crond