Haproxy+PXC搭建Mysql集群

安裝環(huán)境

centos7, docker

集群方案介紹

大型網(wǎng)站數(shù)據(jù)庫需要應(yīng)對高負(fù)載、實現(xiàn)高可用。而單節(jié)點數(shù)據(jù)庫在并發(fā)量大的情況下無法滿足性能要求,且一臺宕機,整個服務(wù)受影響。

  • Mysql集群:PXC
  • 負(fù)載均衡:Haproxy
  • 高可用:Keepalived
高可用Mysql集群方案

搭建pxc集群

安裝pxc鏡像

docker官方倉庫(https://hub.docker.com)搜索 percona-xtradb-cluster,拉取鏡像命令為: docker pull percona/percona-xtradb-cluster
終端執(zhí)行:

// 安裝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

創(chuàng)建Docker內(nèi)部網(wǎng)絡(luò)

出于安全考慮,不要把pxc容器的IP直接暴露出去,而是創(chuàng)建docker內(nèi)部網(wǎng)絡(luò)。

// 網(wǎng)段subnet自定義,網(wǎng)段名自定義為network20
? docker network create --subnet=172.20.0.0/16 network20
2e9196b0637074cad609be8e4e890aa3e889209af8c2b55ce8097981000bf53f
// 查看網(wǎng)段詳細(xì)信息
? docker network inspect network20

創(chuàng)建Docker卷

docker的使用原則之一:不要在容器內(nèi)保存業(yè)務(wù)數(shù)據(jù),而應(yīng)該保存在宿主機中。
實現(xiàn)方式:通過目錄映射,把宿主機的目錄映射到容器內(nèi),運行容器時,把數(shù)據(jù)保存在映射目錄中,也就是保存在宿主機中。當(dāng)容器發(fā)生故障時,只需把故障容器刪除掉,重新啟動一個容器,把宿主機的目錄映射給新容器。
pxc運行在容器中,無法直接使用映射目錄,會發(fā)生閃退。需要借助Docker卷完成映射。

// 創(chuàng)建一個docker卷,自定義名稱為 volume-mysql-1
? docker volume create --name volume-mysql-1
// 可以查看數(shù)據(jù)卷在宿主機上當(dāng)真實目錄
? docker volume inspect volume-mysql-1
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/volume-mysql-1/_data", // 數(shù)據(jù)卷在宿主機真實的路徑
        "Name": "volume-mysql-1", // 數(shù)據(jù)卷名稱
        "Options": {},
        "Scope": "local"
    }
]

創(chuàng)建PXC容器

  • 命令分解
// -d 創(chuàng)建出的容器后臺運行
docker run -d
// -p 端口映射,[宿主機端口]:[容器端口]
-p 3311:3306
// -e 啟動參數(shù),MYSQL_ROOT_PASSWORD數(shù)據(jù)庫root密碼
-e MYSQL_ROOT_PASSWORD=123456
// CLUSTER_NAME集群名稱
-e CLUSTER_NAME=pxc-test 
// XTRABACKUP_PASSWORD數(shù)據(jù)庫間節(jié)點同步密碼
-e XTRABACKUP_PASSWORD=123456 
// -v 目錄映射,[宿主機目錄(數(shù)據(jù)卷)]:[容器目錄]
-v volume-mysql-1:/var/lib/mysql
// 最高權(quán)限
--privileged
// --name 容器名稱
--name mysql-node1
// --net 給容器指定網(wǎng)段,指定IP
--net network20 --ip 172.20.0.2 
// 鏡像名
pxc

執(zhí)行指令創(chuàng)建第一個pxc節(jié)點

// 創(chuàng)建第一個pxc節(jié)點 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

注意:容器創(chuàng)建很快就會完成,但是容器內(nèi)mysql數(shù)據(jù)庫的初始化大概需要2分鐘左右,一定要等到mysql初始化完成后,再創(chuàng)建第2個容器,否則第2個容器會發(fā)生閃退! 判斷mysql-node1是否完成初始化,可以在宿主機終端執(zhí)行指令:docker exec -it mysql-node1 mysql -uroot -p,看是否連接成功。

創(chuàng)建第2-5個pxc節(jié)點,與第1個節(jié)點略有區(qū)別:

  • 修改映射宿主機端口號(-p)
  • 修改容器名稱 (--name)
  • 修改映射的數(shù)據(jù)卷 (-v)
  • 修改分配的IP地址 (--ip)
  • 增加一個參數(shù)用于加入集群,和第一個pxc節(jié)點進行同步: -e CLUSTER_JOIN=mysql-node1
  • 除第1個容器以外,其余mysql初始化時間非常短,無需等待
// 創(chuàng)建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
// 創(chuàng)建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
// 創(chuàng)建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
// 創(chuàng)建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集群的數(shù)據(jù)同步

可在宿主機上直接登陸某個容器的mysql客戶端;也可以使用mysql可視化工具,如Navicat等遠(yuǎn)程登陸,遠(yuǎn)程登陸的需要防火墻開放端口。
以下演示宿主機終端驗證方法:

// 登陸mysql-node1節(jié)點的mysql終端,創(chuàng)建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)
// 其它節(jié)點同mysql-node2

任意節(jié)點寫入新數(shù)據(jù),其它節(jié)點都會同步。至此,pxc集群搭建完成。

haproxy配置負(fù)載均衡

負(fù)載均衡簡單介紹

負(fù)載均衡可以使應(yīng)用數(shù)據(jù)均勻的落在pxc集群的每一個節(jié)點上。如果不使用負(fù)載均衡,單節(jié)點處理所有請求,會導(dǎo)致該節(jié)點負(fù)載高、性能差;其它節(jié)點卻空閑浪費。
haproxy做負(fù)載均衡器,它不是數(shù)據(jù)庫,只是一個轉(zhuǎn)發(fā)件。


負(fù)載均衡器

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

創(chuàng)建haproxy配置文件

// 宿主機上創(chuàng)建haproxy配置文件,路徑自己指定,之后創(chuàng)建容器會用到
? touch /home/softconf/haproxy/haproxy.cfg
// haproxy.conf寫入下列內(nèi)容,具體配置需要修改
global
    #工作目錄
    chroot /usr/local/etc/haproxy
    #日志文件,使用rsyslog服務(wù)中l(wèi)ocal5日志設(shè)備(/var/log/local5),等級info
    log 127.0.0.1 local5 info
    #守護進程運行
    daemon

defaults
    log global
    mode    http
    #日志格式
    option  httplog
    #日志中不記錄負(fù)載均衡的心跳檢測記錄
    option  dontlognull
    #連接超時(毫秒)
    timeout connect 5000
    #客戶端超時(毫秒)
    timeout client  50000
    #服務(wù)器超時(毫秒)
    timeout server  50000

#監(jiān)控界面
listen  admin_stats
    #監(jiān)控界面的訪問的IP和端口
    bind  0.0.0.0:8888
    #訪問協(xié)議
    mode        http
    #URI相對地址
    stats uri   /dbs
    #統(tǒng)計報告格式
    stats realm     Global\ statistics
    #登陸帳戶信息
    stats auth  admin:admin123456
#數(shù)據(jù)庫負(fù)載均衡
listen  proxy-mysql
    #訪問的IP和端口
    bind  0.0.0.0:3306
    #網(wǎng)絡(luò)協(xié)議
    mode  tcp
    #負(fù)載均衡算法(輪詢算法)
    #輪詢算法:roundrobin
    #權(quán)重算法:static-rr
    #最少連接算法:leastconn
    #請求源IP算法:source
    balance  roundrobin
    #日志格式
    option  tcplog
    #在MySQL中創(chuàng)建一個沒有權(quán)限的haproxy用戶,密碼為空。Haproxy使用這個賬戶對MySQL數(shù)據(jù)庫心跳檢測
    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相關(guān)配置 重點查看listen proxy-mysql

創(chuàng)建haproxy容器

// -p 端口號 8888 :haproxy后臺監(jiān)控界面端口,與haproxy.cnf中的配置一致
// -p 端口號 3306 :haproxy對外提供負(fù)載均衡服務(wù)端口,可以直接通過該端口連接到pxc集群
// -v 目錄映射,把宿主機的配置文件所在目錄映射到容器的工作目錄中
// --name 容器名,建議帶數(shù)字編號1,高可用時haproxy需要配置成雙節(jié)點
// --net 網(wǎng)段需要和pxc集群在同一網(wǎng)段中
// --ip 可以指定IP,當(dāng)不指定時docker虛擬機會默認(rèn)分配一個
? 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

創(chuàng)建mysql的haproxy用戶

進入pxc某個節(jié)點,在mysql中創(chuàng)建haproxy用戶。haproxy中間件需要使用該賬號登陸數(shù)據(jù)庫,發(fā)送心跳檢測。

// 登陸一個pxc節(jié)點的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監(jiān)控頁面,遠(yuǎn)程訪問需要開放端口(CentOS7使用firewalld打開關(guān)閉防火墻與端口)

  • 訪問地址:http://宿主機IP:4001/dbs
  • 訪問路徑配置文件中:stats uri /dbs
  • 用戶名、密碼在配置文件中:stats auth admin:admin123456
    haproxy監(jiān)控頁面

在監(jiān)控見面中可以看到5個節(jié)點都是啟動狀態(tài),當(dāng)暫停/停止一個pxc節(jié)點時,監(jiān)控界面的down節(jié)點狀態(tài)(顏色)發(fā)生變化。由于haproxy會將請求發(fā)送至其它可用節(jié)點,此時pxc集群仍然可用。

// 終端執(zhí)行命令,暫停一個節(jié)點
?  haproxy docker pause mysql-node2
haproxy監(jiān)控界面 - node down

mysql客戶端連接haproxy

// 宿主機上連接mysql客戶端
// -P 端口號,haproxy的3306端口映射到宿主機的4002端口
// -p 密碼,pxc集群中的mysql密碼
?  haproxy mysql -h127.0.0.1 -P4002 -uroot -p
// 或通過navicat工具連接,-h為宿主機的公網(wǎng)IP

// 進入mysql后,操作的所有數(shù)據(jù)都同步到pxc集群的全部節(jié)點
...

TODO : 集群高可用

單節(jié)點的Haproxy不具備高可用,必須要有冗余設(shè)計。
keepalived與haproxy安裝在同一個容器中,搶占虛擬IP。
阿里云服務(wù)器不支持虛擬IP,keepalived實現(xiàn)高可用待實現(xiàn)

Tips

Keepalived+mysql 雙主一般來說,有幾個需要注意的點,原文地址:MySQL 高可用性keepalived+mysql雙主

1.采用 keepalived 作為高可用方案時,兩個節(jié)點最好都設(shè)置成 BACKUP模式,避免因為意外情況下(比如 腦裂)相互搶占導(dǎo)致往兩個節(jié)點寫入相同數(shù)據(jù)而引發(fā)沖突;
2.把兩個節(jié)點的 auto_increment_increment(自增步長)和 auto_increment_offset(自增起始值)設(shè)成不同值。其目的是為了避免 master 節(jié)點意外宕機時,可能會有部分 binlog 未能及時復(fù)制到slave上被應(yīng)用,從而會導(dǎo)致slave新寫入數(shù)據(jù)的自增值和原先master上沖突了,因此一開始就使其錯開;當(dāng)然了,如果有合適的容錯機制能解決主從自增 ID 沖突的話,也可以不這么做;
3.slave 節(jié)點服務(wù)器配置不要太差,否則更容易導(dǎo)致復(fù)制延遲。作為熱備節(jié)點的 slave 服務(wù)器,硬件配置不能低于 master 節(jié)點;
4.如果對延遲問題很敏感的話,可考慮使用 MariaDB 分支版本,或者直接上線 MySQL 5.7 最新版本,利用多線程復(fù)制的方式可以很大程度降低復(fù)制延遲;

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容