安裝環(huán)境
centos7, docker
集群方案介紹
大型網(wǎng)站數(shù)據(jù)庫需要應(yīng)對高負(fù)載虫几、實現(xiàn)高可用寓娩。而單節(jié)點數(shù)據(jù)庫在并發(fā)量大的情況下無法滿足性能要求趟径,且一臺宕機(jī)雾家,整個服務(wù)受影響英融。
- Mysql集群:PXC
- 負(fù)載均衡:Haproxy
- 高可用:Keepalived
搭建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)該保存在宿主機(jī)中
。
實現(xiàn)方式:通過目錄映射熊响,把宿主機(jī)的目錄映射到容器內(nèi)旨别,運(yùn)行容器時,把數(shù)據(jù)保存在映射目錄中耘眨,也就是保存在宿主機(jī)中昼榛。當(dāng)容器發(fā)生故障時,只需把故障容器刪除掉剔难,重新啟動一個容器胆屿,把宿主機(jī)的目錄映射給新容器。
pxc運(yùn)行在容器中偶宫,無法直接使用映射目錄非迹,會發(fā)生閃退。需要借助Docker卷完成映射纯趋。
// 創(chuàng)建一個docker卷憎兽,自定義名稱為 volume-mysql-1
? docker volume create --name volume-mysql-1
// 可以查看數(shù)據(jù)卷在宿主機(jī)上當(dāng)真實目錄
? docker volume inspect volume-mysql-1
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/volume-mysql-1/_data", // 數(shù)據(jù)卷在宿主機(jī)真實的路徑
"Name": "volume-mysql-1", // 數(shù)據(jù)卷名稱
"Options": {},
"Scope": "local"
}
]
創(chuàng)建PXC容器
- 命令分解
// -d 創(chuàng)建出的容器后臺運(yùn)行
docker run -d
// -p 端口映射,[宿主機(jī)端口]:[容器端口]
-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 目錄映射纯命,[宿主機(jī)目錄(數(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是否完成初始化,可以在宿主機(jī)終端執(zhí)行指令:docker exec -it mysql-node1 mysql -uroot -p
南捂,看是否連接成功吴裤。
創(chuàng)建第2-5個pxc節(jié)點,與第1個節(jié)點略有區(qū)別:
- 修改映射宿主機(jī)端口號(-p)
- 修改容器名稱 (--name)
- 修改映射的數(shù)據(jù)卷 (-v)
- 修改分配的IP地址 (--ip)
- 增加一個參數(shù)用于加入集群溺健,和第一個pxc節(jié)點進(jìn)行同步:
-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ù)同步
可在宿主機(jī)上直接登陸某個容器的mysql客戶端;也可以使用mysql可視化工具枕面,如Navicat等遠(yuǎn)程登陸愿卒,遠(yuǎn)程登陸的需要防火墻開放端口缚去。
以下演示宿主機(jī)終端驗證方法:
// 登陸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é)點卻空閑浪費(fèi)瞭吃。
haproxy做負(fù)載均衡器,它不是數(shù)據(jù)庫涣旨,只是一個轉(zhuǎn)發(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配置文件
// 宿主機(jī)上創(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
#守護(hù)進(jìn)程運(yùn)行
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 目錄映射,把宿主機(jī)的配置文件所在目錄映射到容器的工作目錄中
// --name 容器名辅髓,建議帶數(shù)字編號1泣崩,高可用時haproxy需要配置成雙節(jié)點
// --net 網(wǎng)段需要和pxc集群在同一網(wǎng)段中
// --ip 可以指定IP,當(dāng)不指定時docker虛擬機(jī)會默認(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
// 進(jìn)入容器中洛口,榮國配置文件啟動 haproxy
? docker exec -it mysql-haproxy1 bash
root@0672cb121dde:/# haproxy -f /usr/local/etc/haproxy/haproxy.cfg
創(chuàng)建mysql的haproxy用戶
進(jìn)入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://宿主機(jī)IP:4001/dbs
- 訪問路徑配置文件中:
stats uri /dbs
- 用戶名、密碼在配置文件中:
stats auth admin:admin123456
在監(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
mysql客戶端連接haproxy
// 宿主機(jī)上連接mysql客戶端
// -P 端口號砌左,haproxy的3306端口映射到宿主機(jī)的4002端口
// -p 密碼脖咐,pxc集群中的mysql密碼
? haproxy mysql -h127.0.0.1 -P4002 -uroot -p
// 或通過navicat工具連接,-h為宿主機(jī)的公網(wǎng)IP
// 進(jìn)入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é)點意外宕機(jī)時贝或,可能會有部分 binlog 未能及時復(fù)制到slave上被應(yīng)用,從而會導(dǎo)致slave新寫入數(shù)據(jù)的自增值和原先master上沖突了锐秦,因此一開始就使其錯開咪奖;當(dāng)然了,如果有合適的容錯機(jī)制能解決主從自增 ID 沖突的話酱床,也可以不這么做羊赵;
3.slave 節(jié)點服務(wù)器配置不要太差,否則更容易導(dǎo)致復(fù)制延遲扇谣。作為熱備節(jié)點的 slave 服務(wù)器昧捷,硬件配置不能低于 master 節(jié)點;
4.如果對延遲問題很敏感的話罐寨,可考慮使用 MariaDB 分支版本靡挥,或者直接上線 MySQL 5.7 最新版本,利用多線程復(fù)制的方式可以很大程度降低復(fù)制延遲鸯绿;