超詳細乾貨!Docker+PXC+Haproxy搭建高可用強一致性的MySQL集群

前言

乾貨又來了,全程無廢話,可先看目錄了解。

MySQL搭建集群最常見的是binlog方式,但還有一種方式是強一致性的,能保證集群節點的數據一定能夠同步成功,這種方式就是pxc,本篇就使用圖文方式一步步展示具體的搭建步驟及最終效果。

搭建

本次搭建集群環境以5節點MySQL為例

1、安裝pxc鏡像

拉取pxc鏡像

docker pull percona/percona-xtradb-cluster

111.png

鏡像名稱太長,修改一下:

docker tag percona/percona-xtradb-cluster pxc

222.png

刪除之前的:

docker rmi percona/percona-xtradb-cluster

333.png

2、創建內部網路

創建內部網段,24位,名稱net1:

docker network create --subnet=172.18.0.0/24 net1

444.png

查看net1網段:

docker inspect net1

555.png

刪除net1:(這裡不執行,留作參考。)

docker network rm net1

3、創建docker數據卷

因為pxc不支援映射目錄,所以採用映射數據卷的方式。

創建數據卷叫v1,這裡5個節點,所以創建5個數據卷:

docker volume create v1
docker volume create v2
docker volume create v3
docker volume create v4
docker volume create v5

666.png

查看v1數據卷在宿主機的位置:

docker inspect v1

777.png

刪除數據卷v1:(這裡不執行,留作參考。)

docker volume rm v1

4、創建pxc容器

這裡最好先把備份數據的數據卷創建出來,然後也映射到宿主機,這樣以後做熱備份的時候就不用刪掉容器節點重新再創建容器並映射備份目錄了。

做備份數據的數據卷:

docker volume create backup1
docker volume create backup2
docker volume create backup3
docker volume create backup4
docker volume create backup5

開始創建5個MySQL節點

命令參數說明:埠3306,密碼123456,集群名稱PXC,同步數據密碼123456,映射數據目錄到宿主機的v1數據卷,給予最高許可權,名稱叫node1,網段為net1,ip指定為172.18.0.2,運行的鏡像是pxc。

1)、創建第1個MySQL節點

這裡要注意:一定要等到第一個節點創建並通過客戶端連接成功,才能繼續創建其它的節點,否則因為找不到node1同步庫,其它節點創建時會閃退!
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -v v1:/var/lib/mysql -v backup1:/data --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc

2)、創建第2個MySQL節點

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

3)、創建第3個MySQL節點

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

4)、創建第4個MySQL節點

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

5)、創建第5個MySQL節點

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

5、驗證PXC集群

連接5個資料庫節點:
888.png

在DB1中新建一個資料庫test,新建一張表tb_student,新建兩條數據。
999.png

提交後,看其它四個節點是否同步:
1010.png

發現全部同步成功!

6、拉取Haproxy鏡像

docker pull haproxy

7、編寫Haproxy配置文件

在宿主機上編寫:

vim /data/software/haproxy/haproxy.cfg

配置文件如下:(拷貝到Linux中去的時候一定要記得把換行符刪掉,否則報錯。)

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:abc123456
#資料庫負載均衡
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  

注意:

1)、option部分,記得在MySQL創建一個沒有許可權的用戶haproxy;

   CREATE USER ‘haproxy’@’%’ IDENTIFIED BY ”;
1011.png

2)、server部分,記得這裡3306是容器的埠,不是宿主機的埠。

8、創建Haproxy容器並啟動

創建兩個,後面使用Keepalived做高可用。

1)、創建第1個Haproxy負載均衡伺服器

4001映射8888埠,8888是監控介面埠,haproxy埠用4002映射3306;

因為宿主機上之前安裝pxc已經佔用了3306,/data/software/haproxy是宿主機上創建的目錄,映射haproxy容器存放配置文件的目錄/usr/local/etc/haproxy;

名稱起h1,後面要做高可用,給所有許可權,網段和pxc對應,也是net1,ip設為172.18.0.7,鏡像是haproxy。

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

進入h1容器,啟動Haproxy。

# 進入h1容器
docker exec -it h1 bash
# 啟動Haproxy
haproxy -f /usr/local/etc/haproxy/haproxy.cfg
2)、創建第2個Haproxy負載均衡伺服器

docker run -it -d -p 4003:8888 -p 4004:3306 -v /data/software/haproxy:/usr/local/etc/haproxy --name h2 --privileged --net=net1 --ip 172.18.0.8 haproxy

進入h2容器,啟動Haproxy。

# 進入h2容器
docker exec -it h2 bash
# 啟動Haproxy
haproxy -f /usr/local/etc/haproxy/haproxy.cfg

9、瀏覽器訪問Haproxy

訪問地址://192.168.239.132:4001/dbs

這裡的4001是創建容器時映射的8888埠,dbs是haproxy.cfg中的stats uri。

1012.png

測試下關閉一個節點:docker stop node1

刷新頁面:發現node1就變紅了,表示斷開了。

1013.png

注意:

docker start node1重新啟動節點,會有閃退問題,起不起來,解決辦法:

先停掉並刪掉這個容器,別緊張,沒讓你刪除v1數據卷,所以數據丟不了,再重新建一個容器,數據卷還是指向之前那個數據卷,但是cluster-join=node2,隨便和一個正常的普通節點同步就行了。

10、驗證方式

資料庫連接haproxy試試加一條數據,轉發請求後其他資料庫能否同步。

1014.png

H1裡面修改一條數據或添加數據後,轉發請求到其他資料庫,發現可以,並且pxc會同步數據,每個節點都同步了,這就說明我們的Haproxy搭建是OK的。

11、Haproxy雙機熱備

1)、Haproxy容器內安裝Keepalived並設置虛擬IP

注意事項:

雲主機不支援虛擬IP,另外很多公司的網路禁止創建虛擬IP(回家創建),這個需要聯繫公司的網路管理員,讓他開放你要設置的虛擬IP就可以了。還有宿主機一定要關閉防火牆和SELINUX,很多人都因為這個而失敗的,切記切記。

h1容器安裝Keepalived,apt加速可自行百度。

# 進入h1容器
docker exec -it h1 bash
# 更新軟體包
apt-get update
# 安裝VIM
apt-get install -y vim
# 安裝Keepalived
apt-get install keepalived
# 編輯Keepalived配置文件(參考下方配置文件)
vim /etc/keepalived/keepalived.conf
# 啟動Keepalived
service keepalived start
# 宿主機執行ping命令,看是否可以ping通虛擬IP。
ping 172.18.0.201

配置文件內容如下:

vrrp_instance  VI_1 {
    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
    }
}

說明:

state=MASTER,表示主服務,會主動爭搶虛擬ip;

interface=eth0,是docker容器內的網卡名稱,要映射宿主機網卡,所以宿主機也要裝一個Keepalived;

virtual_router_id=51,表示虛擬路由id,0-255都可以;

priority=100,表示權重,越高就說明優先順序越高,越容易搶到虛擬ip;

advert_int=1,表示心跳檢測的頻率,這裡就是1秒檢測一次;

authentication,就是心跳檢測訪問的時候需要通過的帳號密碼;

virtual_ipaddress,這就是虛擬ip的設置。

h2容器安裝Keepalived

# 進入h2容器
docker exec -it h2 bash
# 更新軟體包
apt-get update
# 安裝VIM
apt-get install -y vim
# 安裝Keepalived
apt-get install keepalived
# 編輯Keepalived配置文件
vim /etc/keepalived/keepalived.conf
# 啟動Keepalived
service keepalived start
# 宿主機執行ping命令,看是否可以ping通虛擬IP。
ping 172.18.0.201

配置文件內容如下:

vrrp_instance  VI_1 {
    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
    }
}
2)、宿主機安裝Keepalived並設置虛擬ip

主要作用是為了轉發到haproxy容器內的虛擬ip

# 宿主機執行安裝Keepalived
yum -y install keepalived
# 修改Keepalived配置文件
vi /etc/keepalived/keepalived.conf
# 啟動Keepalived
service keepalived start

keepalived.conf配置如下:

記得網卡一定要寫對,用 ip addr 查看。

說明:

1)、virtual_ipaddress就是宿主機設置的虛擬ip;

2)、virtual_server後面的ip和埠就是宿主機的虛擬ip和要轉發的埠;

3)、real_server,就是宿主機轉發到haproxy容器內的虛擬ip,以及轉發到的埠。

這裡的配置含義就是:宿主機設置虛擬ip為192.168.239.150,請求轉發到haproxy容器的172.18.0.201虛擬ip,埠轉發的是8888,3306.

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.239.150
    }
}

virtual_server 192.168.239.150 8888 {
    delay_loop 3
    lb_algo rr
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 172.18.0.201 8888 {
        weight 1
    }
}

virtual_server 192.168.239.150 3306 {
    delay_loop 3
    lb_algo rr 
    lb_kind NAT
    persistence_timeout 50
    protocol TCP

    real_server 172.18.0.201 3306 {
        weight 1
    }

}
3)、驗證

宿主機ping 192.168.239.150,看是否能通;

遠程機ping 192.168.239.150,看是否能通;

1015.png

瀏覽器訪問 //192.168.239.150:8888/dbs ,看是否能連上mysql集群;

不斷刷新,看for pid是否會變化,會變化說明均衡起作用了;

1016.png

1017.png

用客戶端連接192.168.239.150,試試添加或修改數據,看集群節點是否會同步數據;

docker pause h1,將h1容器暫停,再試一下4的做法,看能否同步;

docker unpause h1,恢復h1容器。

12、熱備份數據

因為這個工具是安裝在mysql容器內的,所以最好先創建一個數據卷,映射容器內備份的某個目錄,這樣在宿主機上就能看到備份了。

# 宿主機創建數據卷
docker volume create backup

如果創建mysql容器時,沒有映射備份目錄,那麼要先停掉容器,然後刪掉,再重新創建容器並映射備份目錄。

# 停掉容器
docker stop node1

# 刪除容器
docker rm node1

創建容器,映射備份目錄,這裡的backup就是上面創建的數據卷。這裡注意node1停止後,重新創建需要以普通節點方式啟動,否則會閃退,因為node1本身是主節點,停止後主節點就轉移到其它節點去了,這裡我和node2節點同步。

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

熱備份數據

進入node1容器

docker exec -it node1 bash

更新軟體包,這裡執行如果提示沒有許可權(Permission denied),就用docker exec -it -u 0 node1 bash重登錄試試,表示以root用戶登陸docker內linux。

apt-get update

安裝熱備工具

apt-get install percona-xtrabackup-24

全量熱備

innobackupex --user=root --password=123456 /data/backup/full

13、冷還原數據

停止節點,並刪除節點。

docker stop node1
docker stop node2
docker stop node3
docker stop node4
docker stop node5

docker rm node1
docker rm node2
docker rm node3
docker rm node4
docker rm node5

刪除數據卷

docker volume rm v1
docker volume rm v2
docker volume rm v3
docker volume rm v4
docker volume rm v5

重新創建數據卷

docker volume create v1
docker volume create v2
docker volume create v3
docker volume create v4
docker volume create v5

啟動容器

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=123456 -v v1:/var/lib/mysql -v backup1:/data --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc

node1容器中刪除MySQL的數據並還原

# 刪除數據
rm -rf /var/lib/mysql/*

# 清空事務
innobackupex --user=root --password=123456
--apply-back /data/backup/full/2019-02-17_08-53-07/

# 還原數據
innobackupex --user=root --password=123456 
--copy-back /data/backup/full/2019-02-17_08-53-07/

重新啟動容器

docker stop node1
docker start node1

這個時候,可能會閃退,查看日誌錯誤如下:

1018.png

說是對ibdata1這文件沒有寫入許可權,

那我們不妨全局搜一下這文件,看是哪個目錄的:

find / -name ibdata1,可以看到在backup備份目錄和v1的數據卷目錄都有。

那我們直接給這兩個目錄最大許可權:

chmod -R 777 /var/lib/docker/volumes/backup/_data

chmod -R 777 /var/lib/docker/volumes/v1/_data

然後再次啟動容器。

1019.png

啟動後,驗證前面「node1容器中刪除MySQL的數據並還原」這一步看是否還原成功,用工具連接資料庫查看。

總結

這些環境的搭建其實是偏向於運維層面的,很多Java工程師可能覺得用不上,但不會搭建和你完全不知道是兩碼事,有一篇手記存底,閑暇之餘自己嘗試搭建下,對你日後的職業發展一定是有好處的。

分享

8年多工作及學習過程中在雲筆記中記錄了很多內容,我閑暇之餘都做了下整理,本篇也是其中之一,有感興趣的朋友可以私信我獲取,什麼時候用到了翻開說不定就能節省很多時間。


本人原創文章純手打,覺得有一滴滴幫助就請點個推薦吧~
本人持續分享實際工作經驗和主流技術,喜歡的話可以關注下哦~