docker搭建数据库高可用方案PXC

297 阅读9分钟

搭建MySql集群(PXC方案: 不建议选择这套方案)

这篇文章是从其他文章分离出来的

下载pxc

docker pull percona/percona-xtradb-cluster:5.7

图片中笔者本来想配置mysql8.0的pxc方案, 但主机的ssl配置成功后,从机的ssl一直验证不通过(笔者给予了几个文件足够的权限777). 主机ssl的几个文件必须是读写执行权限全给才能够验证成功, 但从机的custom.cnf权限如果还是读写执行权限将会被忽略, 所以笔者创建了两个config文件夹, 里面存了两个custom.cnf配置文件, 只有权限不同, 虽然这个配置文件不再被忽略, 但还是不行, 会不断的重复尝试连接ssl//:172.18.0.2:4567, 没辙. 只能回到5.7的怀抱
docker搭建mysql8.0的pxc方案相关资料

创建docker内部网络

docker network create --subnet=172.18.0.0/24 pxc_net1

创建docker卷

docker volume create v1
docker volume create v2
docker volume create v3
docker volume create v4
docker volume create v5
docker volume create backup

创建集群

  • 创建主机
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -v v1:/var/lib/mysql -v backup:/data --privileged --name pxc_node1 --net=pxc_net1 --ip=172.18.0.2 percona/percona-xtradb-cluster:5.7
  • 创建从机

集群这几个地方要改

docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc_node1 -v v2:/var/lib/mysql -v backup:/data --privileged --name pxc_node2 --net=pxc_net1 --ip=172.18.0.3 percona/percona-xtradb-cluster:5.7

docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc_node1 -v v2:/var/lib/mysql -v backup:/data --privileged --name pxc_node2 --net=pxc_net1 --ip=172.18.0.3 percona/percona-xtradb-cluster:5.7

docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc_node1 -v v3:/var/lib/mysql -v backup:/data --privileged --name pxc_node3 --net=pxc_net1 --ip=172.18.0.4 percona/percona-xtradb-cluster:5.7

docker run -d -p 3309:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc_node1 -v v4:/var/lib/mysql -v backup:/data --privileged --name pxc_node4 --net=pxc_net1 --ip=172.18.0.5 percona/percona-xtradb-cluster:5.7

docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc_node1 -v v5:/var/lib/mysql -v backup:/data --privileged --name pxc_node5 --net=pxc_net1 --ip=172.18.0.6 percona/percona-xtradb-cluster:5.7

使用Haproxy负载均衡

docker pull haproxy

mkdir ~/docker/haproxy
cd ~/docker/haproxy
vi haproxy.cfg

写入

global
	#工作目录
	chroot /usr/local/etc/haproxy
	#日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
	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
	#统计报告格式
    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数据库心跳检测
	# CREATE USER 'haproxy'@'%' IDENTIFIED by ''; FLUSH PRIVILEGES;
    option  mysql-check user haproxy
    server  MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000
    server  MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000
	server  MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000
	server  MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000
	server  MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000
	#使用keepalive检测死链
    option  tcpka
docker run -it -d -p 4001:8888 -p 4002:3306 -v /root/docker/haproxy:/usr/local/etc/haproxy --name h1 --net=pxc_net1 --ip 172.18.0.8 --privileged haproxy

docker run -it -d -p 4003:8888 -p 4004:3306 -v /root/docker/haproxy:/usr/local/etc/haproxy --name h2 --net pxc_net1 --ip 172.18.0.9 --privileged haproxy

记住这句上面注释掉的CREATE USER 'haproxy'@'%' IDENTIFIED by ''; FLUSH PRIVILEGES; 这句话如果不在数据库中创建好用户, 将会在出现Haproxy无法感知mysql是否启动的情况, 因为她需要通过数据库创建的这个账号haproxy监控数据库情况(所以你可以不给这个账号任何权限, 只要他们访问就行)

所以docker exec -it pxc_node1 /usr/bin/mysql -uroot -p123456进入容器, 然后复制CREATE USER 'haproxy'@'%' IDENTIFIED by ''; FLUSH PRIVILEGES;去创建这个账户

只要在一个节点创建就好, 其他数据库会同步更新

进入docker中的haproxy控制台中 docker exec -it h1 bash

加载配置文件haproxy -f /usr/local/etc/haproxy/haproxy.cfg

之后访问 http://192.168.0.135:4001/dbs

至此配置haproxy配置完成了, 我们使用navicat连接下试试

cf014fbc9ef7        haproxy                              "/docker-entrypoint.…"   2 hours ago         Up 2 hours          0.0.0.0:4002->3306/tcp, 0.0.0.0:4001->8888/tcp   h1

我是尝试连接下 4002端口

现在我们尝试下关闭掉数据库节点pxc_node1

docker stop pxc_node1

我们新建完毕

这里我们其他库都更新完毕了, 但pxc_node1是空的

我们现在重新开启pxc_node1节点看下, 是不是那个表被添加到这个节点了

发现无法开启这个节点了(这是怎么回事???)

vi /var/lib/docker/volumes/v1/_data/grastate.dat 修改 safe_to_bootstrap: 0safe_to_bootstrap: 1

再次尝试启动这个节点

虽然成功了, 但是数据没被同步过去

甚至还会出现这个问题(因为是轮训, 所以随机出现无法找到数据库问题)

现在我们尝试修改下, 别的数据库中的数据(非pxc_node1数据库节点)

这数据就这么丢了

现在我们重启docker, 然后在依次重新启动节点

配置数据库双机热备

为什么需要双机热备???

单个Haproxy节点不具备高可用, 必须要给个备机防止主机没了, 导致我们的服务无法访问的问题

linux提供了虚拟IP的技术, 我们的双机热备需要利用它(虚拟ip就是在一个网卡上可以对不同的程序提供不同的虚拟ip)

使用keepalived方式以抢占虚拟IP的方式完成, 所以我们需要在docker haproxy内部配置环境

完整方案

安装keepalived

  • Keepalived必须要安装在Haproxy所在的容器之内
apt-get update
apt-get upgrade
apt install keepalived
  • keepalived配置文件

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.18.0.201
    }
}

启动keepalived serivce keepalived start 启动它

以上操作都在docker容器中操作

然后我们测试下主机是否能够ping通docker内部的网络下的虚拟机

ping 172.18.0.201

  • 另一个docker中的keepalived配置
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.18.0.202
    }
}

serivce keepalived start 启动它

退出回到宿主机, ping 172.18.0.202看下是否能够ping的通

  • 宿主机安装keepalived

vi /etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 123456
    }
    virtual_ipaddress {
        192.168.0.155
    }
}

virtual_server 192.168.0.155 8888 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 172.18.0.201 8888 {
        weight 1
    }
    real_server 172.18.0.202 8888 {
        weight 1
    }
}

virtual_server 192.168.0.155 3306 {
    delay_loop 6
    lb_algo rr 
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

	real_server 172.18.0.201 3306 {
        weight 1
    }
    real_server 172.18.0.202 3306 {
        weight 1
    }
}

启动keepalived, systemctl start keepalived(宿主机是centOS7, 所以使用systemctl)

再ping下ping 192.168.0.155

[root@centOS ~]# ping 192.168.0.155
PING 192.168.0.155 (192.168.0.155) 56(84) bytes of data.
From 192.168.0.144 icmp_seq=1 Destination Host Unreachable
From 192.168.0.144 icmp_seq=2 Destination Host Unreachable
From 192.168.0.144 icmp_seq=3 Destination Host Unreachable
From 192.168.0.144 icmp_seq=4 Destination Host Unreachable
^C
--- 192.168.0.155 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3000ms
pipe 4
[root@centOS ~]# ping 192.168.0.155
PING 192.168.0.155 (192.168.0.155) 56(84) bytes of data.
64 bytes from 192.168.0.155: icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from 192.168.0.155: icmp_seq=2 ttl=64 time=0.048 ms
64 bytes from 192.168.0.155: icmp_seq=3 ttl=64 time=0.039 ms
^C

注意下: keepalived的启动需要一点点时间, 上面控制台输出Destination Host Unreachable是因为压根没启动完毕

我们回到真正的主机(window上)在ping下, 看下行不行 ping 192.168.0.155

正在 Ping 192.168.0.155 具有 32 字节的数据:
来自 192.168.0.155 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.0.155 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.0.155 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.0.155 的回复: 字节=32 时间<1ms TTL=64

192.168.0.155 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 0ms,最长 = 0ms,平均 = 0ms

ok, 配置完成

我们在navicat上连接下

ip: 192.168.0.155
用户: root
密码: 123456(我为了简便设置了简单的密码, 实际项目中千万别这么简单)
端口: 3306

完成

  • 但存在一个问题, 每次启动docker, 都要进入docker h1和h2容器中再启动keepalived, 挺麻烦的, 放心后面会慢慢解决的
  • 还存在一个问题, 用户无法知道keepalived哪些节点能用, 哪些节点不能用了 keepalived容易出现脑裂, 所以我也不太推荐使用这种方案, 本方案主要目的是学习

热备方案

冷备份和热备份之间的关系是会不会实际影响到我们的业务(锁住备份区域,或者干脆阻塞它), 冷备会, 热备份不会, 显而易见, 选热备

而热备方案中又有全量备份增量备份物理备份

真的是, 各种名词看腻了, 说白了就是一次备份是不是直接 copy 还是 copy + 1 这样的不断备份, 还有一种就是忽略了文件系统结构的备份

我们选择xtrabackup做热备方案

还记得前面我在创建集群时加的参数么? -v backup:/data这个, 现在我们要将数据库备份映射到这个目录, 如果前面创建集群时, 没有增加这个参数需要stop后删除的重新创建

如果我们没有添加映射备份目录, 那么需要

docker stop pxc_node1
docker rm pxc_node1
docker run -d -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc_node2 --net=pxc_net1 --ip=172.18.0.2 -p 3306:3306  -v v1:/var/lib/mysql -v backup:/data --privileged --name pxc_node1 percona/percona-xtradb-cluster:5.7

现在我们进入docker容器中的pxc_node1节点 看看这个容器运行的系统是什么版本的linux系统

red hat 或者 centOS 系统所以我们需要使用yum去更新

docker exec -it pxc_node1 bash

bash-4.2$ yum update
Loaded plugins: fastestmirror, ovl
ovl: Error while doing RPMdb copy-up:
[Errno 13] Permission denied: '/var/lib/rpm/.dbenv.lock'
You need to be root to perform this command.

exit退出, 然后docker exec -it --user root pxc_node1 bash or docker exec -it --user=root pxc_node1 bash

yum clean all
yum makecache
yum update
yum install wget
wget https://repo.percona.com/yum/percona-release-latest.noarch.rpm
rpm -ivh percona-release-latest.noarch.rpm
rm percona-release-latest.noarch.rpm
yum list | grep percona

进行一次全量热备

innobackupex --user=root --password=123456 /data/backup/full

回到宿主机, 看看

docker volume inspect backup

cd /var/lib/docker/volumes/backup/_data

就可以看到已经备份了

所有的pxc_node* 节点都是共享的 backup 目录

还原也一样

docker exec -it pxc_node1 bash # 进入节点
rm -rf /var/lib/mysql/* # 删除掉原本的数据
# 将还没有提交的事务回滚
innobackupex --user=root --password=lezhu123456 --apply-back /data/backup/full/2018-04-15_05-09-07/
# 恢复
innobackupex --user=root --password=lezhu123456 --copy-back /data/backup/full/2018-04-15_05-09-07/

不是我说, 有更好的选择千万别选pxc