docker搭建mysql(集群+高可用+热备份)
docker搭建mysql(集群+高可用+热备份)
Mysql集群(PXC)
PXC介绍
Percona XtraDB Cluster(简称PXC集群)提供了MySQL高可用的一种实现方法。
PXC特性
PXC最大的优势:强一致性、无同步延迟
PXC的优点
- 服务高可用;
- 数据同步复制(并发复制),几乎无延迟;
- 多个可同时读写节点,可实现写扩展,不过最好事先进行分库分表,让各个节点分别写不同的表或者库,避免解决数据冲突;
- 新节点可以自动部署,部署操作简单;
- 数据严格一致性,尤其适合电商类应用;
- 完全兼容MySQL;
PXC使用4个端口号
- mysql实例端口:3306
- PXC cluster相互通讯的端口:4567
- 用于SST传送的端口:4444
- 用于IST传送的端口:4568
一些名词介绍
- WS:write set 写数据集
- IST: Incremental State Transfer 增量同步
- SST:State Snapshot Transfer 全量同步, SST支持的方法有:mysqldump,rsync ,xtrabackup 。
Docker容器安装
下载PXC镜像:https://hub.docker.com/r/percona/percona-xtradb-cluster
docker pull percona/percona-xtradb-cluster:5.7
创建网络:
集群的数据库都连接这个网络,通过它通信
docker network create --subnet=172.20.0.0/24 net1
创建数据卷:
- v1-v3服务于为3台percona
- backup为热备份做准备
docker volume create v1docker volume create v2docker volume create v3docker volume create backup
创建3台PXC容器:
- XTRABACKUP_PASSWORD:数据库节点同步密码
- 启动第一个容器的时候,容器创建是很快的,但是容器里的数据库实例初始化是很费时的,必须等它完成后才能启动第二个容器,判断就在物理机上用navicat 客户端去连接。
第一台容器搭建
docker run -d -p 3311:3306 -v v1:/var/lib/mysql -v backup:/data -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 --privileged --name=mysql_node1 --net=net1 --ip 172.20.0.2 percona/percona-xtradb-cluster:5.7
第二三台需要加入配置-e CLUSTER_JOIN=mysql_node1 加入mysql_node1集群
docker run -d -p 3312:3306 -v v2:/var/lib/mysql -v backup:/data -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql_node1 --privileged --name=mysql_node2 --net=net1 --ip 172.20.0.3 percona/percona-xtradb-cluster:5.7
docker run -d -p 3312:3306 -v v2:/var/lib/mysql -v backup:/data -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql_node1 --privileged --name=mysql_node2 --net=net1 --ip 172.20.0.3 percona/percona-xtradb-cluster:5.7
这样集群就建好了,可以在任意数据库进行测试
当docker里所有pxc都停掉时,集群就失败了,重启需要从mysql_node1开始重启
- 定位到数据卷v1
cd /var/lib/docker/volumes/v1/_data
-
修改grastate.dat
-
启动mysql_node1容器即可
docker start mysql_node1
负载均衡(HAProxy)
介绍
- 如果一组计算机节点提供相同的(同质的)服务,那么对服务的请求就应该均匀的分摊到这些节点上。
- 负载均衡的作用在于,通过某种负载分担技术,解决并发压力,提高应用处理性能;提供故障转移,实现高可用;
- 通过添加或减少服务器数量,提供网站伸缩性;同时也有安全防护的作用。
软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第三方应用的软负载实现。
LVS(Linux虚拟服务器)就是基于Linux操作系统实现的一种软负载,
基于第三方应用的软负载实现就很多了:
HAProxy、Nginx、Apache都是这类软件。
- LVS:不能在虚拟机上使用,Docker容器里用不了。
- HAProxy相比LVS的使用要简单很多,功能方面也很丰富。HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,免费、是快速并且可靠的一种解决方案。
- Nginx在1.9版本之前是只能配置http协议的,不接受tcp协议的代理,所以Nginx最常见还是服务器的负载均衡。
- Apache不支持tcp协议,数据库负载均衡一般用tcp协议来做。
对数据库做负载均衡,采用HAProxy来做,成熟一些。
下载HAProxy镜像:
docker pull haproxy:2.3-dev3
创建HAProxy的配置文件:/opt/docker/haproxy/haproxy.cfg
global#工作目录chroot /usr/local/etc/haproxy#日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级infolog 127.0.0.1 local5 info#守护进程运行daemondefaultslogglobalmodehttp#日志格式optionhttplog#日志中不记录负载均衡的心跳检测记录optiondontlognull#连接超时(毫秒)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#统计报告格式stats realm Global\ statistics#登陆帐户信息stats auth admin:123456#数据库负载均衡listen proxy-mysql#访问的IP和端口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 haproxyserver MySQL_1 172.20.0.2:3306 check weight 1 maxconn 2000 server MySQL_2 172.20.0.3:3306 check weight 1 maxconn 2000 server MySQL_3 172.20.0.4:3306 check weight 1 maxconn 2000 #使用keepalive检测死链,是在TCP中一个可以检测死连接的机制option tcpka
在任意数据库中执行一下命令
CREATE USER 'haproxy'@'%' IDENTIFIED BY '';
创建HAProxy容器并执行haproxy命令
docker run -itd -p 4001:8888 -p 3306:3306 -v /opt/docker/haproxy:/usr/local/etc/haproxy --name haproxy1 --privileged --net=net1 --ip 172.20.0.5 haproxy:2.3-dev3 haproxy -f /usr/local/etc/haproxy/haproxy.cfg
到这里负载均衡就实现完成了,可以用navicat测试连接haproxy
也可以通过浏览器输入ip:4001/dbs查看 账号:admin 密码:123456
高可用(Keepalived)
前面实现了负载均衡,所有的容器收到的请求都在一个haproxy容器转发的,所以haproxy容器完蛋,所有容器也都会完蛋,不存在高可用的特性,想要高可用,一个haproxy容器挂了,对外的服务不能挂,所以必须至少还得有一台备份的一个haproxy容器待命。
实现的关键技术:
1. 虚拟IP
就是一块网卡上边可以有多个ip,然后无论到哪个ip的流量都会经过物理网卡。
大部分虚拟ip基本上都用于高可用的架构上边。主机启用虚拟ip,所有访问的请求都会到主机。
当主机宕机的时候,高可用软件会将主机的虚拟ip down掉,然后在备机上启用虚拟ip。
这样就完成了主备切换。从而保证业务的可用性。
2. Keepalived
Keepalived就是一个具体的上面说的一款高可用软件,它的作用是检测服务器的状态,
如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,
同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,
这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。
了解了前面两个关键技术后,总体的架构设计:
根据上面的总体架,创建第二个hapoxy容器h2:
docker run -itd -p 4002:8888 -p 3307:3306 -v /opt/docker/haproxy:/usr/local/etc/haproxy --name haproxy2 --privileged --net=net1 --ip 172.20.0.6 haproxy:2.3-dev3 haproxy -f /usr/local/etc/haproxy/haproxy.cfg
在Hapoxy容器hapoxy1和hapoxy2里安装Keepalived,配置虚拟IP地址
- 进入hapoxy1和hapoxy2容器
docker exec -it -u root haproxy1 bash
- 安装工具
由于容器默认使用的是ubantu系统,apt-get源是国外的源,下载比较慢,所以我们需要换到国内的源
mv /etc/apt/sources.list /etc/apt/sources.list.bakecho "">> /etc/apt/sources.listecho "deb http://mirrors.ustc.edu.cn/debian stable main contrib non-free" >> /etc/apt/sources.listecho "deb http://mirrors.ustc.edu.cn/debian stable-updates main contrib non-free" >>/etc/apt/sources.list
安装所需工具
apt-get updateapt-get install -y iproute2 #安装ip工具apt-get install -y vim #安装vimapt-get install -y procps #ps命令apt-get install -y keepalived #安装Keepalived,配置虚拟IP地址
- 在Hapoxy容器里,编辑keepalived的配置文件:/etc/keepalived/keepalived.conf:
vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 172.20.0.15 }}
下面说明:
vrrp_instance VI_1 {vrrp_instance用来定义对外提供服务的VIP区域及其相关属性,Virtual Router Redundancy Protocol一般指虚拟路由器冗余协议。 state MASTER 实例初始状态可以是MASTER 或 BACKUP interface eth0 实例节点固有IP(非VIP)的网卡,用来发VRRP包 virtual_router_id 51 虚拟路由标识即VRID 相同的VRID为一个组 他将决定多播的MAC地址 priority 100 定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER 的优先级必须大于BACKUP。 advert_int 1 检查间隔默认为1秒 authentication { 设置认证 auth_type PASS 认证方式可以是PASS或AH两种认证方式 auth_pass 123456 认证密码 } virtual_ipaddress { 设置虚拟IP 可以设置多个 172.20.0.15 }}
- 在Hapoxy容器里,启动keepalived:
service keepalived start
宿主机安装Keepalived,实现双机热备
- 宿主机执行安装Keepalived
yum -y install keepalived
- 修改Keepalived配置文件
vim /etc/keepalived/keepalived.conf
vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress {192.168.175.150 }}virtual_server 192.168.175.150 8889 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 172.20.0.15 8889 { weight 1 }}virtual_server 192.168.175.150 4306 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 172.20.0.15 3306 { weight 1 }}
下面是说明:
virtual_server 192.168.175.150 4306 { #定义RealServer对应的VIP及服务端口,IP和端口之间用空格隔开 delay_loop 6 #每隔6秒查询realserver状态 lb_algo rr #lvs调度算法rr|wrr|lc|wlc|lblc|sh|dh lb_kind NAT #负载均衡转发规则NAT|DR|RUN #persistence_timeout 60 #会话保持时间 protocol TCP #用TCP协议检查realserver状态 real_server 172.20.0.15 3306 { weight 1 #权重,最大越高,lvs就越优先访问 } }
- 启动Keepalived
systemctl start keepalived
热备份(xtrabackup)
热备份
- 进入node1容器
docker exec -it -u root mysql_node1 bash
- 检测工具,没有才安装热备工具
xtrabackup -vyum install percona-xtrabackup-24
- 全量热备份
innobackupex --user=xtrabackup --password=123456 /data/backup/full
- –user=xtrabackup #xtrabackup会自动给我们创建一个xtrabackup用户用于备份,如没有此用户可以用root用户代替
- –password=123456 #数据库密码
- /data/backup/full #数据备份位置,与前面定义的数据卷对应
冷还原数据
docker stop mysql_node1 mysql_node2 mysql_node3 #关闭所有容器docker rm mysql_node1 mysql_node2 mysql_node3 #移除所有容器docker volume rm v1 v2 v3 #删掉所有数据卷 docker volume create v1 #创建新的数据卷cd /var/lib/docker/volumes/backup/_data/backup/full #进入数据卷backup目录可以看到一个 2022-04-24_14-33-59的文件,这个就是我们的备份文件了docker run -d -p 3306:3306 -v v1:/var/lib/mysql -v backup:/data -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 --privileged --name=mysql_node1 --net=net1 --ip 172.20.0.2 percona/percona-xtradb-cluster:5.7#启动容器docker exec -it -u root mysql_node1 bash #进入容器innobackupex --defaults-file=/etc/my.cnf --user=root --password=123456 --apply-log /data/backup/full/2022-04-24_14-33-59/ #node1容器中删除MySQL的数据,注这里的2022-04-24_14-33-59为数据卷中的文件名rm -fr /var/lib/mysql/* innobackupex --user=root --password=123456 --copy-back /data/backup/full/2022-04-24_14-33-59/ #正式还原数据,注这里的2022-04-24_14-33-59为数据卷中的文件名chown -R mysql:mysql /var/lib/mysql/* docker restart mysql_node1 #退出容器并启动