Haproxy+PXC搭建Mysql集群

作者: Avery_up | 来源:发表于2019-04-02 13:34 被阅读144次

    安装环境

    centos7, docker

    集群方案介绍

    大型网站数据库需要应对高负载、实现高可用。而单节点数据库在并发量大的情况下无法满足性能要求,且一台宕机,整个服务受影响。

    • Mysql集群:PXC
    • 负载均衡:Haproxy
    • 高可用:Keepalived
    高可用Mysql集群方案

    搭建pxc集群

    安装pxc镜像

    docker官方仓库(https://hub.docker.com)搜索 percona-xtradb-cluster,拉取镜像命令为: docker pull percona/percona-xtradb-cluster
    终端执行:

    // 安装pxc镜像
    ➜ docker pull percona/percona-xtradb-cluster
    // 查看镜像
    ➜ docker images
    REPOSITORY                                        TAG                 IMAGE ID            CREATED             SIZE
    docker.io/percona/percona-xtradb-cluster        latest              f3abd21f393a        3 days ago          72.1 MB
    // 镜像名称太长,为方便使用,修改一下
    ➜ docker tag docker.io/percona/percona-xtradb-cluster pxc
    // 删除原镜像
    docker rmi docker.io/percona/percona-xtradb-cluster
    

    创建Docker内部网络

    出于安全考虑,不要把pxc容器的IP直接暴露出去,而是创建docker内部网络。

    // 网段subnet自定义,网段名自定义为network20
    ➜ docker network create --subnet=172.20.0.0/16 network20
    2e9196b0637074cad609be8e4e890aa3e889209af8c2b55ce8097981000bf53f
    // 查看网段详细信息
    ➜ docker network inspect network20
    

    创建Docker卷

    docker的使用原则之一:不要在容器内保存业务数据,而应该保存在宿主机中
    实现方式:通过目录映射,把宿主机的目录映射到容器内,运行容器时,把数据保存在映射目录中,也就是保存在宿主机中。当容器发生故障时,只需把故障容器删除掉,重新启动一个容器,把宿主机的目录映射给新容器。
    pxc运行在容器中,无法直接使用映射目录,会发生闪退。需要借助Docker卷完成映射。

    // 创建一个docker卷,自定义名称为 volume-mysql-1
    ➜ docker volume create --name volume-mysql-1
    // 可以查看数据卷在宿主机上当真实目录
    ➜ docker volume inspect volume-mysql-1
    [
        {
            "Driver": "local",
            "Labels": {},
            "Mountpoint": "/var/lib/docker/volumes/volume-mysql-1/_data", // 数据卷在宿主机真实的路径
            "Name": "volume-mysql-1", // 数据卷名称
            "Options": {},
            "Scope": "local"
        }
    ]
    

    创建PXC容器

    • 命令分解
    // -d 创建出的容器后台运行
    docker run -d
    // -p 端口映射,[宿主机端口]:[容器端口]
    -p 3311:3306
    // -e 启动参数,MYSQL_ROOT_PASSWORD数据库root密码
    -e MYSQL_ROOT_PASSWORD=123456
    // CLUSTER_NAME集群名称
    -e CLUSTER_NAME=pxc-test 
    // XTRABACKUP_PASSWORD数据库间节点同步密码
    -e XTRABACKUP_PASSWORD=123456 
    // -v 目录映射,[宿主机目录(数据卷)]:[容器目录]
    -v volume-mysql-1:/var/lib/mysql
    // 最高权限
    --privileged
    // --name 容器名称
    --name mysql-node1
    // --net 给容器指定网段,指定IP
    --net network20 --ip 172.20.0.2 
    // 镜像名
    pxc
    

    执行指令创建第一个pxc节点

    // 创建第一个pxc节点 mysql-node1
    ➜ docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc-test -e XTRABACKUP_PASSWORD=123456 -v volume-mysql-1:/var/lib/mysql --privileged --name mysql-node1 --net network20 --ip 172.20.0.2 pxc
    

    注意:容器创建很快就会完成,但是容器内mysql数据库的初始化大概需要2分钟左右,一定要等到mysql初始化完成后,再创建第2个容器,否则第2个容器会发生闪退! 判断mysql-node1是否完成初始化,可以在宿主机终端执行指令:docker exec -it mysql-node1 mysql -uroot -p,看是否连接成功。

    创建第2-5个pxc节点,与第1个节点略有区别:

    • 修改映射宿主机端口号(-p)
    • 修改容器名称 (--name)
    • 修改映射的数据卷 (-v)
    • 修改分配的IP地址 (--ip)
    • 增加一个参数用于加入集群,和第一个pxc节点进行同步: -e CLUSTER_JOIN=mysql-node1
    • 除第1个容器以外,其余mysql初始化时间非常短,无需等待
    // 创建pxc容器 mysql-node2
    ➜ docker run -d -p 3312:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc-test -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql-node1 -v volume-mysql-2:/var/lib/mysql --privileged --name mysql-node2 --net network20 --ip 172.20.0.3 pxc
    // 创建pxc容器 mysql-node3
    ➜ docker run -d -p 3313:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc-test -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql-node1 -v volume-mysql-3:/var/lib/mysql --privileged --name mysql-node3 --net network20 --ip 172.20.0.4 pxc
    // 创建pxc容器 mysql-node4
    ➜ docker run -d -p 3314:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc-test -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql-node1 -v volume-mysql-4:/var/lib/mysql --privileged --name mysql-node4 --net network20 --ip 172.20.0.5 pxc
    // 创建pxc容器 mysql-node5
    ➜ docker run -d -p 3315:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc-test -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=mysql-node1 -v volume-mysql-5:/var/lib/mysql --privileged --name mysql-node5 --net network20 --ip 172.20.0.6 pxc
    

    检测pxc集群的数据同步

    可在宿主机上直接登陆某个容器的mysql客户端;也可以使用mysql可视化工具,如Navicat等远程登陆,远程登陆的需要防火墙开放端口。
    以下演示宿主机终端验证方法:

    // 登陆mysql-node1节点的mysql终端,创建db=demo,table=user
    ➜ docker exec -it mysql-node1 mysql -uroot -p
    mysql> create database demo;
    mysql> use demo
    Database changed
    Query OK, 1 row affected (0.02 sec)
    mysql> create table student(id int unsigned not null auto_increment, name varchar(50) not null default '', primary key (id)) engine=innodb;
    Query OK, 0 rows affected (0.04 sec)
    mysql> exit
    Bye
    
    // 退出mysql-node1,登陆mysql-node2
    ➜ docker exec -it mysql-node2 mysql -uroot -p
    mysql> use demo
    Database changed
    mysql> show tables;
    +----------------+
    | Tables_in_demo |
    +----------------+
    | student        |
    +----------------+
    1 row in set (0.01 sec)
    // 其它节点同mysql-node2
    

    任意节点写入新数据,其它节点都会同步。至此,pxc集群搭建完成。

    haproxy配置负载均衡

    负载均衡简单介绍

    负载均衡可以使应用数据均匀的落在pxc集群的每一个节点上。如果不使用负载均衡,单节点处理所有请求,会导致该节点负载高、性能差;其它节点却空闲浪费。
    haproxy做负载均衡器,它不是数据库,只是一个转发件。


    负载均衡器

    Docker安装Haproxy镜像

    // 拉取镜像
    ➜ docker pull haproxy
    // 查看镜像
    ➜ docker images
    REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
    docker.io/haproxy           latest              f3abd21f393a        3 days ago          72.1 MB
    pxc                         latest              70b3670450ef        4 weeks ago         408 MB
    

    创建haproxy配置文件

    // 宿主机上创建haproxy配置文件,路径自己指定,之后创建容器会用到
    ➜ touch /home/softconf/haproxy/haproxy.cfg
    // haproxy.conf写入下列内容,具体配置需要修改
    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:admin123456
    #数据库负载均衡
    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.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
        server  MySQL_4 172.20.0.5:3306 check weight 1 maxconn 2000
        server  MySQL_5 172.20.0.6:3306 check weight 1 maxconn 2000
        #使用keepalive检测死链
        option  tcpka
    

    haproxy.cnf 与pxc相关配置 重点查看listen proxy-mysql

    创建haproxy容器

    // -p 端口号 8888 :haproxy后台监控界面端口,与haproxy.cnf中的配置一致
    // -p 端口号 3306 :haproxy对外提供负载均衡服务端口,可以直接通过该端口连接到pxc集群
    // -v 目录映射,把宿主机的配置文件所在目录映射到容器的工作目录中
    // --name 容器名,建议带数字编号1,高可用时haproxy需要配置成双节点
    // --net 网段需要和pxc集群在同一网段中
    // --ip 可以指定IP,当不指定时docker虚拟机会默认分配一个
    ➜ docker run -it -d -p 4001:8888 -p 4002:3306 -v /home/softconf/haproxy:/usr/local/etc/haproxy --name mysql-haproxy1 --privileged --net=network20 haproxy
    // 进入容器中,荣国配置文件启动 haproxy
    ➜ docker exec -it mysql-haproxy1 bash
    root@0672cb121dde:/# haproxy -f /usr/local/etc/haproxy/haproxy.cfg
    

    创建mysql的haproxy用户

    进入pxc某个节点,在mysql中创建haproxy用户。haproxy中间件需要使用该账号登陆数据库,发送心跳检测。

    // 登陆一个pxc节点的mysql终端
    ➜ docker exec -it mysql-node2 mysql -uroot -p
    mysql> use mysql
    Database changed
    mysql> create user 'haproxy'@'%' identified by '';
    mysql> flush privileges;
    

    验证haproxy

    通过浏览器访问haproxy监控页面,远程访问需要开放端口(CentOS7使用firewalld打开关闭防火墙与端口)

    • 访问地址:http://宿主机IP:4001/dbs
    • 访问路径配置文件中:stats uri /dbs
    • 用户名、密码在配置文件中:stats auth admin:admin123456
      haproxy监控页面

    在监控见面中可以看到5个节点都是启动状态,当暂停/停止一个pxc节点时,监控界面的down节点状态(颜色)发生变化。由于haproxy会将请求发送至其它可用节点,此时pxc集群仍然可用。

    // 终端执行命令,暂停一个节点
    ➜  haproxy docker pause mysql-node2
    
    haproxy监控界面 - node down

    mysql客户端连接haproxy

    // 宿主机上连接mysql客户端
    // -P 端口号,haproxy的3306端口映射到宿主机的4002端口
    // -p 密码,pxc集群中的mysql密码
    ➜  haproxy mysql -h127.0.0.1 -P4002 -uroot -p
    // 或通过navicat工具连接,-h为宿主机的公网IP
    
    // 进入mysql后,操作的所有数据都同步到pxc集群的全部节点
    ...
    

    TODO : 集群高可用

    单节点的Haproxy不具备高可用,必须要有冗余设计。
    keepalived与haproxy安装在同一个容器中,抢占虚拟IP。
    阿里云服务器不支持虚拟IP,keepalived实现高可用待实现

    Tips

    Keepalived+mysql 双主一般来说,有几个需要注意的点,原文地址:MySQL 高可用性keepalived+mysql双主

    1.采用 keepalived 作为高可用方案时,两个节点最好都设置成 BACKUP模式,避免因为意外情况下(比如 脑裂)相互抢占导致往两个节点写入相同数据而引发冲突;
    2.把两个节点的 auto_increment_increment(自增步长)和 auto_increment_offset(自增起始值)设成不同值。其目的是为了避免 master 节点意外宕机时,可能会有部分 binlog 未能及时复制到slave上被应用,从而会导致slave新写入数据的自增值和原先master上冲突了,因此一开始就使其错开;当然了,如果有合适的容错机制能解决主从自增 ID 冲突的话,也可以不这么做;
    3.slave 节点服务器配置不要太差,否则更容易导致复制延迟。作为热备节点的 slave 服务器,硬件配置不能低于 master 节点;
    4.如果对延迟问题很敏感的话,可考虑使用 MariaDB 分支版本,或者直接上线 MySQL 5.7 最新版本,利用多线程复制的方式可以很大程度降低复制延迟;

    参考资料

    相关文章

      网友评论

        本文标题:Haproxy+PXC搭建Mysql集群

        本文链接:https://www.haomeiwen.com/subject/rkuwbqtx.html