docker搭建mysql集群

一、集群方案

1、Replication

  • 速度快,但仅能保证弱一致性,适用于保存价值不高的数据,比如日志、帖子、新闻等。
  • 采用master-slave结构,在master写入会同步到slave,能从slave读出;但在slave写入无法同步到master。
  • 采用异步复制,master写入成功就向客户端返回成功,但是同步slave可能失败,会造成无法从slave读出的结果
  • 需要该方案的请查看我的另一篇文章:https://www.cnblogs.com/lvlinguang/p/15205389.html

2、PXC (Percona XtraDB Cluster)

  • 速度慢,但能保证强一致性,适用于保存价值较高的数据,比如订单、客户、支付等。
  • 数据同步是双向的,在任一节点写入数据,都会同步到其他所有节点,在任何节点上都能同时读写。
  • 采用同步复制,向任一节点写入数据,只有所有节点都同步成功后,才会向客户端返回成功。事务在所有节点要么同时提交,要么不提交。

二、服务器配置

1、服务器

  • 服务器一:192.168.3.13:3310、192.168.3.13:3311、192.168.3.13:3312
  • 服务器二:192.168.3.14:3310、192.168.3.14:3311、192.168.3.14:3312

2、开放以上端口,用于单节点访问

# 用于容器网络发现
firewall-cmd --zone=public --add-port=3310/tcp --permanent
firewall-cmd --zone=public --add-port=3311/tcp --permanent
firewall-cmd --zone=public --add-port=3312/tcp --permanent

firewall-cmd --reload

3、配置ntp服务,确保时间同步

 [root@localhost ~]# yum -y install ntp ntpdate
 [root@localhost ~]# ntpdate 0.asia.pool.ntp.org
 [root@localhost ~]# hwclock --systohc
 [root@localhost ~]# date
 2021年 10月 20日 星期三 12:54:23 CST

4、创建Docker Swarm集群

  • 开放以下端口
# 用于集群管理通信的TCP端口
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
  • 创建swarm集群
docker swarm init

将里面的值复制出来,在其它服务器上分别执行,如下图

  • swarm基础操作(扩展)
# 查看swarm集群的所有节点(只能在主节点上查询)
docker node ls

# 删除一个节点
docker node rm -f [节点的ID]

# 解散swarm集群
1、在manager节点上删除所有worker节点
2、强制删除自己,执行:docker swarm leave -f
3、在各个worker节点主机上执行:docker swarm leave

5、创建Docker虚拟网络

  • 出于安全考虑,给PXC集群创建Docker内部虚拟网络,用于PXC集群独立使用
# 创建虚拟网段
docker network create -d overlay --subnet=10.8.0.0/24 --attachable swarm_mysql

# 查看虚拟网络
docker network inspect swarm_mysql

#所有虚拟网络
docker network ls

# 删除网段
# docker network rm swarm_mysql
 

三、安装PXC集群

1、安装镜像

docker pull percona/percona-xtradb-cluster:5.7.33

2、重命名镜像(缩短镜像名称)

docker tag percona/percona-xtradb-cluster:5.7.33 pxc

# 移除原镜像
docker rmi percona/percona-xtradb-cluster:5.7.33

3、创建数据卷(pxc无法直接存取宿组机的数据,所以创建三个docker数据卷)

docker volume create v1
docker volume create v2
docker volume create v3

# 查看数据卷位置
#docker inspect v1

# 删除数据卷
#docker volume rm v1

4、创建容器

  • 第一个节点创建完成之后,需要等1分钟左右才能创建后面的节点。可以通过navicat连接第一个节点测试下,可以连接就说明可以了
#第一台服务器


#创建第1个MySQL节点
docker run -d --name=mysql-node1 -p 3310:3306 --privileged=true -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql --net=swarm_mysql --ip 10.8.0.2 pxc

#创建第2个MySQL节点
docker run -d --name=mysql-node2 -p 3311:3306 --privileged=true -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=mysql-node1 -v v2:/var/lib/mysql --net=swarm_mysql --ip 10.8.0.3 pxc

#创建第3个MySQL节点
docker run -d --name=mysql-node3 -p 3312:3306 --privileged=true -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=mysql-node1 -v v3:/var/lib/mysql --net=swarm_mysql --ip 10.8.0.4 pxc


#第二台服务器


#创建第4个MySQL节点
docker run -d --name=mysql-node4 -p 3310:3306 --privileged=true -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=mysql-node1 -v v1:/var/lib/mysql --net=swarm_mysql --ip 10.8.0.5 pxc

#创建第5个MySQL节点
docker run -d --name=mysql-node5 -p 3311:3306 --privileged=true -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=mysql-node1 -v v2:/var/lib/mysql --net=swarm_mysql --ip 10.8.0.6 pxc

#创建第6个MySQL节点
docker run -d --name=mysql-node6 -p 3312:3306 --privileged=true -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=mysql-node1 -v v3:/var/lib/mysql --net=swarm_mysql --ip 10.8.0.7 pxc

5、查看虚拟网络,观察各节点ip是否配置进去了

docker network inspect swarm_mysql

6、测试集群

  • 通过navicat连接任意一个数据库,进行增、删、改操作操作,观察其它库是否进行同步操作

四、Haproxy负载均衡

  • 虽然搭建了集群,但是不使用数据库负载均衡,单节点处理所有请求,负载高,性能差,如下图

  • 使用Haproxy做负载均衡,可以将请求均匀地发送给每个节点,单节点负载低,性能好,如下图

1、安装haproxy镜像

docker pull haproxy:2.3.13

2、新建目录

mkdir -p /home/apps/haproxy

3、新建Haproxy配置文件

vim /home/apps/haproxy/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数据库心跳检测
    option  mysql-check user haproxy
    server  mysql-node1 10.8.0.2:3306 check weight 1 maxconn 2000
    server  mysql-node2 10.8.0.3:3306 check weight 1 maxconn 2000
    server  mysql-node3 10.8.0.4:3306 check weight 1 maxconn 2000
    server  mysql-node4 10.8.0.5:3306 check weight 1 maxconn 2000
    server  mysql-node5 10.8.0.6:3306 check weight 1 maxconn 2000
    server  mysql-node6 10.8.0.7:3306 check weight 1 maxconn 2000
    #使用keepalive检测死链
    option  tcpka

3、在数据库集群中创建空密码、无权限用户haproxy,来供Haproxy对MySQL数据库进行心跳检测

# 进入容器
docker exec -it mysql-node1 /bin/bash

# 登录mysql
mysql -uroot -p123456

# 创建用户
create user 'haproxy'@'%' identified by '';

4、创建第1个Haproxy负载均衡服务器

docker run -it -d --name haproxy-node1 -p 4001:8888 -p 4002:3306 --restart always --privileged=true -v /home/apps/haproxy:/usr/local/etc/haproxy --net=swarm_mysql haproxy:2.3.13

5、启动Haproxy

# 进入容器
docker exec -it haproxy-node1 /bin/bash

# 启动haproxy
haproxy -f /usr/local/etc/haproxy/haproxy.cfg

五、访问测试

1、页面访问

  • ip:4001/dbs,在配置文件中定义有用户名admin,密码123456

2、数据库访问

  • 使用navacat访问代理集群,端口为4002

3、测试docker挂掉

  • 分别下线第二和第四个节点,通过访问其它节点或代理节点都能正常使用

六、节点宕机或重启

1、从节点宕机后的操作

  • 如果指定的主节点没有宕机,直接启动从节点容器,数据会自动同步

2、主节点宕机后的操作

  • 【重启用此操作】如果主节点是最后一个离开集群的(说明数据是最新的),只要重启主节点即可,主节点的启动需要设置safe_to_bootstrap: 1 才能启动
# 修改grastate.dat
vim /var/lib/docker/volumes/v1/_data/grastate.dat

# 将以下值改为1
safe_to_bootstrap: 1

# 启动主节点
docker start mysql-node1
  • 如果其他节点还在运行中,主节点挂掉了(说明主节点的数据已经不是最新的了),需要删除主节点容器,原来的数据卷无需删除(继续使用,避免数据丢失),然后再以从节点方式加入集群,注意加参数 "-e CLUSTER_JOIN=mysql-node2",指定可用的从节点启动
docker run -d --name=mysql-node1 -p 3310:3306 --privileged=true -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=mysql-node2 -v v1:/var/lib/mysql --net=net1 --ip 172.18.0.2 pxc

3、另一种启动方式,删除集群容器和数据卷中的grastate.dat文件,重新创建

  • 该方案会以主节点的数据恢复,如果主节点数据不是最新的,会造成数据丢失
# 移除容器
docker rm mysql-node1 mysql-node2 mysql-node3 mysql-node4 mysql-node5

# 移除数据卷中的grastate.dat文件
rm -rf /var/lib/docker/volumes/v1/_data/grastate.dat
rm -rf /var/lib/docker/volumes/v2/_data/grastate.dat
rm -rf /var/lib/docker/volumes/v3/_data/grastate.dat
rm -rf /var/lib/docker/volumes/v4/_data/grastate.dat
rm -rf /var/lib/docker/volumes/v5/_data/grastate.dat


# 按上面的方式重新创建集群容器

七、参考

posted @ 2021-08-31 17:02  吕林光  阅读(1046)  评论(1编辑  收藏  举报