我是基于ChatGPT-turbo-3.5实现的AI助手,在此网站上负责整理和概括文章
本文介绍了Linux系统下Docker的轻量级虚拟机特性及防火墙管理,详细阐述了Docker容器的安装、运行与维护。重点讨论了MySQL单节点的缺点,并比较了PXC和Replication集群方案,展示了PXC的同步复制和高可用性优势。还涉及了HAProxy负载均衡、Keepalived高可用配置以及数据库热备份方法,提供了构建可靠数据库系统的实用指南。
# Linux回顾
Docker创建的所有虚拟实例共用同一个Linux内核,对硬件占用较小,属于轻量级虚拟机


# 防火墙
查看、启动、关闭、重启防火墙
firewall-cmd -state -start -stop -restart
端口管理
firewall-cmd -permanent --add-port=8080-8085/tcp
firewall-cmd -reload
firewall-cmd -permanent-remove-port=8080-8085/tcp
firewall-cmd --list-ports 查看端口
firewall-cmd–permanent–list-services 查看使用网络的程序
# Docker说明

# 安装Java镜像
docker search java
docker pull java
# 导入导出镜像
docker save java > /home/java.tar.gz
docker load < /home/java.tar.gz
docker images
docker rmi java
# 运行容器
docker run -it --name myjava java bash
# 端口映射 -p 宿主机:镜像
docker run -it --name myjava -p 9000:8080 java bash
# 映射文件 -v --privileged:container内的root拥有真正的root权限。
docker run -it --name myjava -v /home/project/soft --privileged java bash
# 容器自动重启
docker update --restart=always [container-name]
no 默认值,表示容器退出时,docker不自动重启容器
on-failure 若容器的退出状态非0,则docker自动重启容器,还可以指定重启次数,若超过指定次数未能启动容器则放弃
always 容器退出时总是重启
unless-stopped 容器退出时总是重启,但不考虑Docker守护进程启动时就已经停止的容器
# 进入容器
docker run -itd --name busy --net=net1 --ip 10.0.75.11 -e "DOCKER_GATEWAY=10.0.75.1" busybox
docker exec -it busy sh
# 暂停、停止容器
docker pause myjava
docker unpause myjava
docker stop myjava
docker start -i myjava
# 单节点缺点
大型互联网程序用户群体庞大,所以架构必须要特殊设计
单节点的数据库无法满足性能上的要求
单节点的数据库没有冗余设计,无法满足高可用
# Mysql集群方案
- PXC 集群方案:
- 所有节点都是可读可写的,PXC 同步机制是同步进行的,它能保证数据强一致性
- Replication集群方案:
- Replication从节点不能写入,主从同步是单向的,无法从slave节点向master点同步
- Replication同步机制是异步进行的,它如果从节点停止同步,依然可以向主节点插入数据,正确返回,造成数据主从数据的不一致性。
- PXC 是用牺牲性能保证数据的一致性,Replication在性能上是高于PXC的。所以两者用途也不一致。
- PXC是用于重要信息的存储,例如:订单、用户信息等。
- Replication用于一般信息的存储,能够容忍数据丢失,例如:购物车,用户行为日志等。


# PXC (Percona XtraDB Cluster)
PXC是针对MySQL用户的高可用性和扩展性解决方案,基于Percona Server(MySQL改进版,性能提升很大) 。
Percona Server 是MySQL的改进版本,使用 XtraDB 存储引擎,在功能和性能上较 MySQL 有着很显著的提升,如提升了在高负载情况下的 InnoDB 的性能,为 DBA 提供了一些非常有用的性能诊断工具,另外有更多的参数和命令来控制服务器行为。

# PXC的作用
- 同步复制,事务可以在所有节点上提交。
- 多主机复制,你可以写到任何节点。
- 从( slave)服务器上的并行应用事件,真正的“并行复制”。
- 自动节点配置。
- 数据一致性,不再有未同步的从服务器
# PXC集群的注意事项
- 尽可能的控制PXC集群的规模,节点越多,数据同步速度越慢
- 所有 PXC节点的硬件配置要一致,如果不一致,配置低的节点将拖慢数据同步速度
- PXC集群只支持InnoDB引擎,不支持其他的存储引擎
# 安装PXC镜像
docker pull percona/percona-xtradb-cluster:5.7.21
docker load < /home/soft/pxc.tar.gz
# 创建内部网络
处于安全考虑,需要给PXC集群实例创建Docker内部网络 docker内置网段172.17.0.*
# 创建网段
docker network create --subnet=10.0.75.1/24 net1
docker network inspect net1
docker network rm net1
# 创建Docker卷
业务数据保存在宿主机中
# pxc无法映射目录,只能创建数据卷,分别创建mysql数据卷和配置卷
# docker volume rm mysql-data
# docker volume rm mysql-conf
docker volume create mysql-data
docker volume create mysql-conf
# 可以去挂载的配置卷去修改my.cnf
[root@centos7 ~]# docker inspect mysql-conf
[
{
"CreatedAt": "2023-06-15T21:46:38+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mysql-conf/_data",
"Name": "mysql-conf",
"Options": null,
"Scope": "local"
}
]
docker volume create --name v1
docker volume create --name v2
docker volume create --name v3
docker volume create --name v4
docker volume create --name v5
# 创建PXC容器
只需要向PXC镜像传入运行参数就能创建出PXC容器
注意:要等待前一个docker镜像中的mysql初始化(数据库初始化比较耗时),如果第一个没有初始化成功,就提前创建了第二个数据库,第二个数据库就会闪退
[root@centos7 ~]# docker rm $(docker ps -a -q) -f
# 第一个节点 -v mysql-data:/var/lib/mysql -v mysql-conf:/etc/mysql
docker run -d -p 4406:3306 \
-e TZ=Asia/Shanghai -e MYSQL_ROOT_PASSWORD=abc123456 \
-e CLUSTER_NAME=PXC -e EXTRABACKUP_PASSWROD=abc123456 \
-v v1:/var/lib/mysql \
--privileged --name=mysql-node1 \
--net=net1 --ip 10.0.75.11 percona/percona-xtradb-cluster:5.7.21
# 查看日志
docker logs -f mysql-node1
# 使用docker ps命令可以看到容器已经启动成功,使用navicat等工具连接 如果连接成功就表示第一个节点已经成功启动
# 到/var/lib/docker/volumes/mysql-conf_data下面的my.cnf更改配置文件,然后重新启动容器
vim /var/lib/docker/volumes/mysql-conf/_data/my.cnf
docker restart mysql-node1
# 启动成功后连接到服务器上执行命令查看是否修改成功
select @@GLOBAL.sql_mode
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
# 部署第二个节点
跟第一台服务器一样,创建两个数据卷,然后直接启动容器
# 第二个节点 docker rm mysql-node2 -f
docker run -d -p 4407:3306 -e TZ=Asia/Shanghai -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=mysql-node1 --privileged -v v2:/var/lib/mysql --name=mysql-node2 --net=net1 --ip 10.0.75.12 percona/percona-xtradb-cluster:5.7.21
# docker logs mysql-node2
# docker exec -it mysql-node2 bash
# 验证
create database test DEFAULT CHARSET=utf8;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
insert user (name) values("zs1");
select * from user;
# 注意: 在 PXC 集群中使用了多个节点,并且使用了 HAProxy 进行负载均衡。由于每个节点都管理自己的自增计数器,因此在多个节点上插入数据时,自增 ID 可能会在节点之间不连续。
# 解决此问题的一种方法是在每个表上禁用自增 ID 的使用,而是使用应用程序生成的 UUID 或另一个唯一标识符作为记录主键。这将确保您的应用程序在任何节点上插入记录时都能保持唯一性。
# 并发写入的时候,负载均衡把请求分发给不同的pxc节点。A节点写入记录使用了主键值1,没来得及提交事务的时候。B节点写入记录发现主键值1没人使用,所以用了主键值1。这时候A节点提交事务,通知B节点,主键值1我已经用了。B节点回复A节点,主键1我在使用,所以两个节点都放弃主键1,继续用下一个主键值尝试写入记录,所以主键值就不连续了。正确的做法是用程序生成主键值,放弃数据库主键自增长
# 停止启动pxc
使用 docker stop <container_name> 命令时没有正确停止 PXC 服务,可能会导致数据文件损坏或丢失
-
进入正在运行的 PXC 容器:
docker exec -it <container_name> bash docker exec -it mysql-node1 bash docker exec -it mysql-node2 bash -
在容器中运行以下命令停止 PXC 服务:
docker exec -it mysql-node1 service mysql stop docker exec -it mysql-node2 service mysql stop -
退出容器:
exit -
停止 PXC 容器:
docker stop mysql-node1 docker stop mysql-node2 -
启动
docker start mysql-node1 docker exec -it mysql-node1 service mysql start docker start mysql-node2 docker exec -it mysql-node2 service mysql start
# 使用haproxy进行负载均衡

如果单纯是想做pxc集群的话上面的步骤已经完成,但是想要使用负载均衡来使用pxc集群的话,我们可以使用haproxy工具
# 拉取haproxy镜像
#拉取haprox镜像 haproxytech/haproxy-ubuntu
docker pull haproxytech/haproxy-ubuntu
# 配置haproxy
在任一节点(mysql-node1,mysql-node2)上执行下面命令进入容器
docker exec -it mysql-node1 bash
# 进入容器后执行:
mysql -uroot -p
# 输入上面设置的密码 后执行:
create user 'haproxy'@'%' identified by '';
# 新建配置文件
#新建目录
mkdir -p /data/haproxy
#新建配置文件
vi /data/haproxy/haproxy.cfg
haproxy.cfg配置
global
#工作目录,这边要和创建容器指定的目录对应
# chroot /usr/local/etc/haproxy
#日志文件
log 127.0.0.1 local5 info
#守护进程运行
daemon
defaults
log global
mode http
#日志格式
option httplog
#日志中不记录负载均衡的心跳检测记录
option dontlognull
#连接超时(毫秒)
timeout connect 5000
#客户端超时(毫秒)
timeout client 50000
#服务器超时(毫秒)
timeout server 50000
#监控界面
listen admin_stats
#监控界面的访问的IP和端口
bind 0.0.0.0:8888
#访问协议
mode http
#URI相对地址
stats uri /dbs_monitor
#统计报告格式
stats realm Global\ statistics
#登陆帐户信息
stats auth admin:admin
#数据库负载均衡
listen proxy-mysql
#访问的IP和端口,haproxy开发的端口为3306
#假如有人访问haproxy的3306端口,则将请求转发给下面的数据库实例
bind 0.0.0.0:3306
#网络协议
mode tcp
#负载均衡算法(轮询算法)
#轮询算法:roundrobin
#权重算法:static-rr
#最少连接算法:leastconn
#请求源IP算法:source
balance roundrobin
#日志格式
option tcplog
#在MySQL中创建一个没有权限的haproxy用户,密码为空。
#Haproxy使用这个账户对MySQL数据库心跳检测
option mysql-check user haproxy
server MySQL_1 10.0.75.11:3306 check weight 1 maxconn 2000
server MySQL_2 10.0.75.12:3306 check weight 1 maxconn 2000
#使用keepalive检测死链
option tcpka
# 启动haproxy容器
#在主节点创建haproxy容器 docker rm -f ha01
docker run -d --restart=always -p 8888:8888 -p 3307:3306 -v /data/haproxy:/usr/local/etc/haproxy \
--name ha01 --net=net1 -e "DOCKER_GATEWAY=10.0.75.1" --privileged haproxy
# docker restart ha01
# 验证是否启动成功
输入地址 http://192.168.61.10:8888/dbs_monitor admin/admin
如果出现如下图两个节点都是绿色状态则说明连接成功,两个节点都是正常的状态

测试连接

# 高可用
单节点Haproxy不具备高可用,必须要有冗余设计。

使用Keepalived实现双机热备

# exit是退出容器界面 ctrl+D 退出容器
docker exec -u root -it ha01 bash
# 将系统的镜像更换为国内的镜像源
cp /etc/apt/sources.list /etc/apt/sources.list.bak
echo "
deb https://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb https://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
" > /etc/apt/sources.list
#更新镜像源
apt-get update
#安装keepalived
apt-get install keepalived
#安装vim
apt-get install vim
yum install keepalived
Keepalived的配置文件是/etc/keepalived/keepalived.conf
最后一步 service keepalived start
# 热备份数据
mysqldump属于冷备份
冷备份是关闭数据库时候的备份方式,通常做法是拷贝数据文件
冷备份是最简单最安全的一种备份方式
大型网站无法做到关闭业务备份数据,所以冷备份不是最佳选择
冷备份是关闭数据库时候的备份方式,通常做法是拷贝数据文件
冷备份是最简单最安全的一种备份方式
大型网站无法做到关闭业务备份数据,所以冷备份不是最佳选择

热备份是在系统运行的状态下备份数据,也是难度最大的备份
MySQL常见的热备份有LVM和XtraBackup两种方案
建议使用XtraBackup热备MySQL
- XtraBackup备份过程不锁表、快速可靠
- XtraBackup备份过程不会打断正在执行的事务
- XtraBackup能够基于压缩等功能节约磁盘空间和流量
LVM备份需要锁表,只能读
全量备份是备份全部数据。备份过程时间长,占用空间大
增量备份是只备份变化的那部分数据。
创建数据卷
docker volume create backup
然后映射backup数据卷,因为是先删除之前的节点,这个时候要关联node2节点
docker run -d -p 4406:3306 -v v1:/f/skillTrain -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v backup:/f/data -e CLUSTER_JOIN=node2 --privileged --name=node1 --net=net1 --ip 10.0.75.2 pxc
PXC容器中安装XtraBackup,并执行备份
dcoer exec -it node1 bash
apt-get update
apt-get install percona-xtrabackup-24
innobackupex --user=root --password=abc123456 /data/backup/full
查看数据卷在哪
docker inspect backup
数据库可以热备份,但是不能热还原,只能冷回复。为了避免恢复过程中的数据同步,我们采用空白的MySQL还原数据,然后再建立PXC集群
还原数据前要将未提交的事务回滚,还原数据之后重启MySQL
rm -rf /var/lib/mysql/*
innobackupex --user=root --password=abc123456 --apply-back /data/backup/full/2018/04-15105-09-07/ 回滚
innobackupex --user=root --password=abc123456 --copy-back /data/backup/full/2018/04-15105-09-07/ 还原