天天看点

Docker创建Mysql的PXC集群 PXC介绍安装问题点

PXC介绍

       基于Galera协议的Codership提供多主数据同步复制机制,可以实现多个节点间的数据同步复制以及读写,并且可保障数据库的服务高可用及数据一致性。

       基于Galera的高可用方案主要有MariaDB Galera Cluster和Percona XtraDB Cluster(简称PXC),目前PXC用的会比较多一些。MariaDB的集群原理跟PXC一样,MariDB-Cluster其实就是PXC,两者原理是一样的。要搭建PXC架构至少需要3个mysql实例来组成一个集群,三个实例之间不是主从模式,而是各自为主,所以三者是对等关系,不分从属。

PXC的特性和优点:

PXC的优点

  1. 同步复制
  2. 支持多主复制
  3. 支持并行复制
  4. 作为高可用方案,相比其他方案其结构和实施相对简单明了 
  5. 完全兼容MySQL

PXC的局限和劣势:

  1. 写入效率取决于节点中最弱的一台,因此建议所有的节点配置都一样,因为PXC集群采用的是强一致性原则,一个更改操作在所有节点都成功才算执行成功。
  2. 新加入的节点开销大,需要复制完整的数据。采用SST传输开销太大。
  3. 任何更新事务都需要全局验证通过,才会在每个节点库上执行,集群性能受限于性能最差的节点。
  4. 因为需要保证数据的一致性,所以在多节点并发写时,锁冲突问题比较严重。
  5. 因为使用乐观锁,所以建议使用小事物。
  6. 存在写扩大问题,所有的节点上都会发生相同操作。
  7. 只支持innodb存储引擎的表。
  8. 没有表级别的锁定,执行DDL语句操作会把整个集群锁住,而且也 kill 不了(建议使用Osc操作,即在线DDL)
  9. 所有的表必须含有主键,不然操作数据时会报错。

安装

第一步、拉取PXC镜像

docker pull percona/percona-xtradb-cluster
           

安装完成

[[email protected] ~]# docker pull percona/percona-xtradb-cluster
Using default tag: latest
latest: Pulling from percona/percona-xtradb-cluster
ab5ef0e58194: Pull complete 
8fe559edc254: Pull complete 
5569aa7b8f9c: Pull complete 
fd629efbda5f: Pull complete 
ee4bdc096df0: Pull complete 
1e519408b4ca: Pull complete 
54a7b6e8793f: Pull complete 
02157f8de89f: Pull complete 
ecf8e2634fff: Pull complete 
83b6497fb08d: Pull complete 
50a9f7adc0a6: Pull complete 
Digest: sha256:b65bbdab1a5a699f4cc57f4a10303c18aeb323aa6735303d4a2d9c6c503624ae
Status: Downloaded newer image for percona/percona-xtradb-cluster:latest           

如果拉取镜像下载慢的话参考阿里云镜像加速:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

没有账号密码,注册之后每个人会得到一个加速器地址

Docker创建Mysql的PXC集群 PXC介绍安装问题点

重命名镜像名称

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

查看镜像

[[email protected] ~]# docker images
REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
pxc                                latest              a6a51beefff1        9 days ago          494MB
percona/percona-xtradb-cluster     latest              a6a51beefff1        9 days ago          494MB           

删除老的镜像

[[email protected] ~]# docker rmi percona/percona-xtradb-cluster:latest
Untagged: percona/percona-xtradb-cluster:latest
Untagged: percona/[email protected]:b65bbdab1a5a699f4cc57f4a10303c18aeb323aa6735303d4a2d9c6c503624ae           

第二步、创建内部网络

docker network create --subnet=172.18.0.0/24 net1
           

查看net1详情

docker inspect net1
           
[[email protected] ~]# docker inspect net1
[
    {
        "Name": "net1",
        "Id": "542c05542fde4129ec4f11e8603271ef3c8e94916e6946d2f6bd45c6cab9b40f",
        "Created": "2019-12-26T06:48:20.7274881Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/24"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]           

说明:Subnet=172.18.0.0/24 自定义网段172.18.0.0,24是指24位子网掩码 net1 网段名称。

第三步、创建Docker的volume卷

使用Docker时,业务数据应保存在宿主机中,采用目录映射,这样可以使数据与容器独立。但是容器中的PXC无法直接使用映射目录,解决办法是采用Docker卷来映射

docker volume create --name v1
           

查看v1的内容

docker inspect v1           
[[email protected] ~]# docker inspect v1
[
    {
        "CreatedAt": "2019-12-26T06:52:54Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/v1/_data",
        "Name": "v1",
        "Options": {},
        "Scope": "local"
    }
]           

可以看到:"Mountpoint": "/var/lib/docker/volumes/v1/_data",为v1在宿主机映射的路径

同样的创建其他四个

docker volume create --name v2
docker volume create --name v3
docker volume create --name v4
docker volume create --name v5
           

输入地址命令查看宿主机是否存在映射卷

[[email protected] ~]#  ls /var/lib/docker/volumes/
v1
v2
v3
v4
v5           

第四步、创建PXC容器

创建主节点

docker run -d -p 3306:3306 -v v1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc
           
[[email protected] ~]# docker logs node1
...分割符...
...分割符...
...分割符...
...分割符...
...分割符...
...分割符...
2019-12-26T07:01:35.780499Z 0 [Note] Skipping generation of RSA key pair as key files are present in data directory.
2019-12-26T07:01:35.782039Z 0 [Note] Server hostname (bind-address): '0.0.0.0'; port: 3306
2019-12-26T07:01:35.782581Z 0 [Note]   - '0.0.0.0' resolves to '0.0.0.0';
2019-12-26T07:01:35.782919Z 0 [Note] Server socket created on IP: '0.0.0.0'.
2019-12-26T07:01:35.819138Z 0 [Note] InnoDB: Buffer pool(s) load completed at 191226  7:01:35
2019-12-26T07:01:35.821588Z 0 [Note] Event Scheduler: Loaded 0 events
2019-12-26T07:01:35.822495Z 0 [Note] mysqld: ready for connections.
Version: '5.7.28-31-57'  socket: '/tmp/mysql.sock'  port: 3306  Percona XtraDB Cluster (GPL), Release rel31, Revision ef2fa88, WSREP version 31.41, wsrep_31.41
2019-12-26T07:01:35.826201Z 1 [Note] WSREP: Initialized wsrep sidno 2
2019-12-26T07:01:35.826265Z 1 [Note] WSREP: Auto Increment Offset/Increment re-align with cluster membership change (Offset: 1 -> 1) (Increment: 1 -> 1)
2019-12-26T07:01:35.826299Z 1 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification.
2019-12-26T07:01:35.826341Z 1 [Note] WSREP: Assign initial position for certification: 16, protocol version: 4
2019-12-26T07:01:35.826699Z 0 [Note] WSREP: Service thread queue flushed.
2019-12-26T07:01:35.826773Z 1 [Note] WSREP: GCache history reset: 83f02479-27ad-11ea-a085-5ef3f00475a6:0 -> 83f02479-27ad-11ea-a085-5ef3f00475a6:16
2019-12-26T07:01:35.832775Z 1 [Note] WSREP: Synchronized with group, ready for connections
2019-12-26T07:01:35.832840Z 1 [Note] WSREP: Setting wsrep_ready to true
2019-12-26T07:01:35.832858Z 1 [Note] WSREP: wsrep_notify_cmd is not defined, skipping notification.           

创建第一个节点的时候,要等一会,创建完成用Navicat连接测试一下

Docker创建Mysql的PXC集群 PXC介绍安装问题点

继续创建其他节点

节点2

docker run -d -p 3307:3306 -v v2:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=node1 --privileged --name=node2 --net=net1 --ip 172.18.0.3 pxc

           

节点3

docker run -d -p 3308:3306 -v v3:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=node1 --privileged --name=node3 --net=net1 --ip 172.18.0.4 pxc

           

节点4

docker run -d -p 3309:3306 -v v4:/var/lib/mysql -e MYSQL_ROOT_PASSROWD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=node1 --privileged --name=node4 --net=net1 --ip 172.18.0.5 pxc

           

节点5

docker run -d -p 3310:3306 -v v5:/var/lib/mysql -e MYSQL_ROOT_PASSROWD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=node1 --privileged --name=node5 --net=net1 --ip 172.18.0.6 pxc

           

节点2、3、4、5比主节点多了一个  CUSTER_JOIN=node1  并且端口和ip也不一样

查看容器是否全部启动

[[email protected] ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                   NAMES
7193bb97874f        pxc                 "/entrypoint.sh mysq…"   3 seconds ago       Up 2 seconds        4567-4568/tcp, 0.0.0.0:3310->3306/tcp   node5
e97cbe6eb72e        pxc                 "/entrypoint.sh mysq…"   9 seconds ago       Up 8 seconds        4567-4568/tcp, 0.0.0.0:3309->3306/tcp   node4
bb8bfc9bec92        pxc                 "/entrypoint.sh mysq…"   16 seconds ago      Up 15 seconds       4567-4568/tcp, 0.0.0.0:3308->3306/tcp   node3
ddd897ac960a        pxc                 "/entrypoint.sh mysq…"   2 minutes ago       Up 2 minutes        4567-4568/tcp, 0.0.0.0:3307->3306/tcp   node2
53deabb7b13f        pxc                 "/entrypoint.sh mysq…"   13 minutes ago      Up 13 minutes       0.0.0.0:3306->3306/tcp, 4567-4568/tcp   node1           

第五步、创建Haproxy负载均衡

1. 创建目录

mkdir -p /home/soft/haproxy           

2. 拉取镜像

docker pull haproxy           

3. 宿主机创建配置文件

vim /home/soft/haproxy/haproxy.cfg           

4. 拷贝下面内容到haproxy.cfg

# 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_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           

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

连接Navicat到节点1数据库

Docker创建Mysql的PXC集群 PXC介绍安装问题点

执行语句

create user 'haproxy'@'%' identified by '';           

然后会发现其他四个节点,也都创建了haproxy用户

6. 创建Haproxy容器

  注意:要加 --privileged

docker run -it -d -p 4001:8888 -p 4002:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h1 --net=net1 --ip 172.18.0.7 --privileged haproxy           

 查看容器是否启动

[[email protected] ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                            NAMES
edce88704a33        haproxy             "/docker-entrypoint.…"   45 seconds ago      Up 43 seconds       0.0.0.0:4002->3306/tcp, 0.0.0.0:4001->8888/tcp   h1
7193bb97874f        pxc                 "/entrypoint.sh mysq…"   19 minutes ago      Up 19 minutes       4567-4568/tcp, 0.0.0.0:3310->3306/tcp            node5
e97cbe6eb72e        pxc                 "/entrypoint.sh mysq…"   19 minutes ago      Up 19 minutes       4567-4568/tcp, 0.0.0.0:3309->3306/tcp            node4
bb8bfc9bec92        pxc                 "/entrypoint.sh mysq…"   19 minutes ago      Up 19 minutes       4567-4568/tcp, 0.0.0.0:3308->3306/tcp            node3
ddd897ac960a        pxc                 "/entrypoint.sh mysq…"   21 minutes ago      Up 21 minutes       4567-4568/tcp, 0.0.0.0:3307->3306/tcp            node2
53deabb7b13f        pxc                 "/entrypoint.sh mysq…"   32 minutes ago      Up 32 minutes       0.0.0.0:3306->3306/tcp, 4567-4568/tcp            node1
[[email protected]:/home]$ docker logs h1
[NOTICE] 359/073317 (1) : New worker #1 (8) forked           

7. 进入Haproxy容器内部

docker exec -it h1 bash           

8. 在容器bash中启动Haproxy

haproxy -f /usr/local/etc/haproxy/haproxy.cfg           

9. 在浏览器中访问地址:http://localhost:4001/dbs

会弹出账号和密码,分别为:admin/123456,上述配置文件可以配置

Docker创建Mysql的PXC集群 PXC介绍安装问题点

10. 测试手动数据库掉线,看负载页面变化

挂掉节点2、节点3

docker stop ddd bb8           
Docker创建Mysql的PXC集群 PXC介绍安装问题点

可以看到节点2、3都已经下线了。

11. 使用工具连接hproxy负载数据库

在控制台输入命令

docker ps           

可以看到haproxy的映射端口为4002->3306

[[email protected]:~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                            NAMES
57f824b919df        haproxy             "/docker-entrypoin..."   32 minutes ago      Up 19 minutes       0.0.0.0:4002->3306/tcp, 0.0.0.0:4001->8888/tcp   h1           

将端口改为4002,测试连接如右图。

Docker创建Mysql的PXC集群 PXC介绍安装问题点
Docker创建Mysql的PXC集群 PXC介绍安装问题点

JDBC连接测试

Docker创建Mysql的PXC集群 PXC介绍安装问题点

到此整个mysql集群都已经搭建完成了。

问题点

问题1

问题现象: 启动节点1,报错

2019-12-26T09:01:22.914339Z 0 [ERROR] WSREP: It may not be safe to bootstrap the cluster from this node. It was not the last one to leave the cluster and may not contain all the updates. To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .
2019-12-26T09:01:22.914344Z 0 [ERROR] WSREP: Provider/Node (gcomm://) failed to establish connection with cluster (reason: 7)
2019-12-26T09:01:22.914346Z 0 [ERROR] Aborting           

分析产生原因:

  1. 第一次创建集群的时候,启动没有问题
  2. 当其他节点没有关闭的情况下,主节点node1关闭了,再启动node1节点就会报这个错
  3. docker服务重启,再启动node1节点就会报这个错

解决方式:

查看报错信息:edit the grastate.dat file manually and set safe_to_bootstrap to 1 .

需要编辑 grastate.dat 文件的set safe_to_bootstrap属性设置为1

find / -name grastate.dat            

返回结果

[[email protected] ~]# find / -name grastate.dat 
/var/lib/docker/volumes/v1/_data/grastate.dat
/var/lib/docker/volumes/v2/_data/grastate.dat
/var/lib/docker/volumes/v3/_data/grastate.dat
/var/lib/docker/volumes/v4/_data/grastate.dat
/var/lib/docker/volumes/v5/_data/grastate.dat           

当前启动第一个节点,编辑 

vim /var/lib/docker/volumes/v1/_data/grastate.dat           

文件内容

# GALERA saved state
version: 2.1
uuid:    1918ba7e-27be-11ea-a398-9a561b7556db
seqno:   -1
safe_to_bootstrap: 0           

将 safe_to_bootstrap 值改为1,保存重启即可

或者把该文件删除,重新启动。