mysql 【进阶】 多主集群架构

此方案是伪集群模式!后续研究改进

集群方案

集群方案有两种:ReplicationPercona XtraDB Cluster(PXC)

从目前的程序开发角度看,我们选PXC,相对来说有较强的通用性

PXC的局限

  • 复制只支持InnoDB 引擎,MyISAM(读音:my-z[ei]m)的更改不复制(甚至这种表无法导入);
  • 写入效率取决于节点中最慢的一台。

扩展知识点

Percona Server

Percona Server由领先的MySQL咨询公司Percona发布。
Percona Server是一款独立的数据库产品,其可以完全与MySQL兼容,可以在不更改代码的情况了下将存储引擎更换成XtraDB 。
Percona团队的最终声明是“Percona Server是由Oracle发布的最接近官方MySQL Enterprise发行版的版本”,因此与其他更改了大量基本核心MySQL代码的分支有所区别。Percona Server的一个缺点是他们自己管理代码,不接受外部开发人员的贡献,以这种方式确保他们对产品中所包含功能的控制。
Percona提供高性能XtraDB引擎,还提供PXC高可用解决方案,并且附带perconatoolkit等DBA管理工具箱。

XtraDB

XtraDB存储引擎是由Percona开发的一款MySQL数据库的高性能存储引擎,其目的是用来代替InnoDB存储引擎,可用于需要更高性能的环境

常用端口

3306:数据库对外服务的端口号。
4444:请求SST的端口。
4567:组成员之间进行沟通的一个端口号
4568:用于传输IST。

名词解释

SST(State Snapshot Transfer):全量传输
IST(Incremental state Transfer):增量传输


**
下面正式开始搭建
**

搭建流程

  • 安装docker
  • 基于docker搭建Mysql集群
  • 基于docker搭建Haproxy
  • 进入Haproxy搭建keepaliced

搭建Mysql集群

我的这个案例会搭建5个mysql节点~

拉官方镜像

docker pull percona/percona-xtradb-cluster

注意:它是mysql5!

### 修改镜像

实际生产环境下,对于mysql配置文件有个性化需求,因此,我们需要修改这官方镜像

创建docker卷

如果用-v /data/mysql/5:/var/lib/mysql方式,我试过有权限问题

docker volume create m5
docker volume create m4
docker volume create m3
docker volume create m2
docker volume create m1

创建局域网

docker network create --driver bridge --subnet 172.25.0.0/16 pxc_net

创建第一个节点

docker run -d -p 3311:3306 --name=m1 -v m1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hexoadmincp2022 -e CLUSTER_NAME=PXC -e XTRABACKUP_PACSSWORD=cpbk2022 --privileged --net=pxc_net --ip 172.25.0.11 percona/percona-xtradb-cluster

创建其他节点

在主节点正常启动后,我们往集群中追加子节点。
要注意第二个节点开始需加 -e CLUSTER_JOIN=m1 ,表示与 m1 节点同步,不加的话 m2 容器会自动关闭。
当 PXC集群中存在两个节点以上之后就没有主节点的概念了。集群中最后一个退出的节点就会变为主节点,在 {mysqlpath}/grastate.dat 文件中属性 safe_to_bootstrap 的值 会从 0 被设置为 1 表示该节点是主节点

docker run -d -p 3315:3306 --name=m5 -v m5:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hexoadmincp2022 -e CLUSTER_NAME=PXC -e CLUSTER_JOIN=m1 -e XTRABACKUP_PACSSWORD=cpbk2022 --privileged --net=pxc_net --ip 172.25.0.15 percona/percona-xtradb-cluster
docker run -d -p 3314:3306 --name=m4 -v m4:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hexoadmincp2022 -e CLUSTER_NAME=PXC -e CLUSTER_JOIN=m1 -e XTRABACKUP_PACSSWORD=cpbk2022 --privileged --net=pxc_net --ip 172.25.0.14 percona/percona-xtradb-cluster
docker run -d -p 3313:3306 --name=m3 -v m3:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hexoadmincp2022 -e CLUSTER_NAME=PXC -e CLUSTER_JOIN=m1 -e XTRABACKUP_PACSSWORD=cpbk2022 --privileged --net=pxc_net --ip 172.25.0.13 percona/percona-xtradb-cluster
docker run -d -p 3312:3306 --name=m2 -v m2:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hexoadmincp2022 -e CLUSTER_NAME=PXC -e CLUSTER_JOIN=m1 -e XTRABACKUP_PACSSWORD=cpbk2022 --privileged --net=pxc_net --ip 172.25.0.12 percona/percona-xtradb-cluster


**
里程碑
进行到这里,你的java程序或者navicat
已经可以通过任意一个ip:port使用mysql集群了
**

搭建Haproxy,让Mysql高可用

上面我们搭建了5个myql节点

目前数据库都是独立的ip,在开发的时候总不能随机连接一个数据库吧

如果想请求,统一的口径,这就需要搭建负载均衡了

虽然上边已经搭建了集群,但是不使用数据库负载均衡,单节点处理所有请求,负载高,性能差。下图就是一个节点很忙,其他节点很闲

调整后的方案,使用Haproxy做负载均衡,请求被均匀分发到每个节点,单节点的负载低,性能好。haproxy不是数据库,只是一个转发器

附负载均衡中间件对比图

拉取ha镜像

docker pull haproxy

配置haproxy.cfg

创建运行目录

mkdir -p /data/haproxy

编辑配置文件

vim /data/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
    #7层 http;4层tcp  如果要让haproxy支持虚拟主机,mode 必须设为http
mode    http
    #日志格式
    option  httplog
    #日志中不记录负载均衡的心跳记录
    option  dontlognull
    #最大连接数
    maxconn 2000
#连接超时(毫秒),下面三个参数要大点,不然java程序连接会爆using a shorter maxLifetime value
    timeout connect 3600000
    #客户端超时(毫秒)
    timeout client  3600000
    #服务器超时(毫秒)
    timeout server  3600000

#监控界面
listen  admin_stats

    #监控界面访问ip和端口
    bind    0.0.0.0:8888
    #访问协议
    mode        http
    #URI相对地址
    stats   uri     /dbs
    #统计报告格式
    stats   realm   Gloal\ statistics
    #登录账户信息 用于登录监控网站使用
    stats   auth    hexoadmincpha:hexoadmincp2022ha

#数据库负载均衡
listen  proxy-mysql

    #访问的IP和端口
    bind    0.0.0.0:3306
    #网络协议
    mode    tcp
    #负载均衡算法(轮询算法)
    #轮询算法:roundrobin
    #权重算法:static-rr
    #最少连接算法:leastconn
    #请求源IP算法:source
    balance roundrobin

    #日志格式
    option  tcplog
    #在MySQL中创建一个没有权限的haproxy用户,密码为空。
    option mysql-check user hexoadmincpha
    server m1 172.25.0.11:3306 check weight 1 maxconn 2000
    server m2 172.25.0.12:3306 check weight 1 maxconn 2000
    server m3 172.25.0.13:3306 check weight 1 maxconn 2000
    server m4 172.25.0.14:3306 check weight 1 maxconn 2000
    server m5 172.25.0.15:3306 check weight 1 maxconn 2000
    #使用keepalive检测死链
    option tcpka

运行haproxy容器

docker run -it -d -p 4001:8888 -p 3308:3306 -v /data/haproxy:/usr/local/etc/haproxy --name ha --privileged --net=pxc_net haproxy

创建心跳账号

在m1上创建用户用于心跳监测(此时也会被同步到PXC其他节点)

create user 'hexoadmincpha'@'%' IDENTIFIED BY '';

访问监控网页

输入我们上面的账号密码 http://ip:4001/dbs


**
里程碑
进行到这里,你的java程序或者navicat
已经可以通过haproxy使用数据库了
**

部署keepalived

我的keepalived教程可能有问题,请多方查阅资料

目前haproxy只有一个,单haproxy不具备高可用,必须冗余设计!

不能让haproxy成为性能瓶颈!!

引入keepalived后的架构图

关于keepalived:

虚拟IP技术,haproxy双机互备离不开一个关键的技术,这个技术是虚拟IP,linux可以在一个网卡内定义多个虚拟IP,得把这些IP地址定义到一个虚拟IP。这里我没搞懂,改天请教同事~

双机热备,设置一个虚拟ip,两个keepalive同时进行抢占该虚拟ip,抢到的为主服务器,没有抢到的为从服务器,从服务器定期向主服务器发送心跳,如果检测到主服务器宕机,从服务便可以获得虚拟ip成为主服务器。

进入Haproxy容器

docker exec -it ha bash

安装keepalived

sudo apt-get update
sudo apt-get install keepalived

配置文件

vi /etc/keepalived/keepalived.conf
vrrp_instance VI_1{
    #表明keepalived身份(MASTER为主服务器,BACKUP为从服务器),主服务器抢占虚拟IP,备用服务器不会抢占IP
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
    }
}

实际项目开展过程中,需要向运营商申请一个同网段的虚拟IP


**
下面是集群维护手册
**

如果我要新上一个节点

假设我新加的节点定义为m6,下面的CLUSTER_JOIN可以是运行中的任意一个节点的名称

docker volume create m6
docker run -d -p 3316:3306 --name=m6 -v m6:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hexoadmincp2022 -e CLUSTER_NAME=PXC -e CLUSTER_JOIN=m1 -e XTRABACKUP_PACSSWORD=cpbk2022 --privileged --net=pxc_net --ip 172.25.0.16 percona/percona-xtradb-cluster

如果节点宕机

假设我是m1宕机,下面的CLUSTER_JOIN可以是运行中的任意一个节点的名称

docker rm m1
docker run -d -p 3311:3306 --name=m1 -v m1:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=hexoadmincp2022 -e CLUSTER_NAME=PXC -e CLUSTER_JOIN=m2 -e XTRABACKUP_PACSSWORD=cpbk2022 --privileged --net=pxc_net --ip 172.25.0.11 percona/percona-xtradb-cluster

查看集群状态

集群中当前其它节点的地址

show status like '%wsrep_incoming_addresses%';

当前节点个数

show status like '%wsrep_cluster_size%';

实验

1、暂停m5容器(docker pause m5),在m4上写入,m1~m3同步正常,恢复m5,此时,m5数据同步正常
2、关闭m5容器,在其他节点写入数据,重启m5,数据同步正常

my.cnf

在容器的这个位置/etc/mysql/node.cnf,怎么在外面改?还没研究出来。

故障 PXC m1节点掉线后无法重启

故障:docker start 后依旧无法重启,查看日志发现:

[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 .

故障分析

错误提示很明显了,因为m1节点不是最后一个离开集群的不能再以主节点的形式启动了,如果要以主节点的形式启动必须调整 grastate.dat文件中的 safe_to_bootstrap 参数为 1。
但是要注意的是因为集群中其他节点并没有关闭,这样启动的容器跟之前的集群就没有关系了数据也不会同步

解决方案

这种情况删除m1容器,重建下,加入集群即可。具体见上面“宕机操作”

故障:WSREP has not prepared…

集群还在同步,等同步完毕就正常了

如果一直显示这样,看看你的宿主机是不是性能不够

java项目报错 Possibly consider using a shorter maxLifetime value

故障
com.zaxxer.hikari.pool.PoolBase : systemDataSource - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@78363803 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.

故障分析:当你java程序连接ha然后,在调试代码时,连接太长会断开(好比前端前期timeout一样)

解决方案:这个是Haproxy参数配置的问题


转载请注明来源。 欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。 可以在下面评论区评论,也可以邮件至 sharlot2050@foxmail.com。

文章标题:mysql 【进阶】 多主集群架构

字数:2.6k

本文作者:夏来风

发布时间:2020-06-08, 16:27:01

原始链接:http://www.demo1024.com/blog/mysql-cluster/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。