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

福隆苑居士發表於2022-06-12

前言

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

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

訪問地址:http://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

瀏覽器訪問 http://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年多工作及學習過程中在雲筆記中記錄了很多內容,我閒暇之餘都做了下整理,本篇也是其中之一,有感興趣的朋友可以私信我獲取,什麼時候用到了翻開說不定就能節省很多時間。



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

相關文章