天天看點

MySQL叢集搭建方案(PXC)

伺服器快過期了,清一點庫存,把運維這塊的知識複習下

為什麼要搭MySQL叢集

技術層面上,傳統的單節點資料庫,萬一當機了,就涼涼了。容災性能差、抗并發能力有限,資料量大的時候查詢有瓶頸。學習層面上,作為一個技術人了解一些技術相關的知識那也是無可厚非,愛折騰嘛。是以、本着“不把雞蛋放在一個籃子裡”的思想,我們來一起探讨學習下如何搭建MySQL叢集。

MySQL叢集的解決方案

關于搭建MySQL叢集解決方案的操作方面,這部分知識其實是很死闆的,沒有特别多的含金量,真正有含金量的是挖掘其背後實作的原理和思路,并能夠曉之以情動之以理地講出來。這裡主要介紹兩種解決方案,我們抓牢它們的側重點總結下吧。

PXC

  • 強一緻性
  • 速度慢
  • 隻支援InnoDB存儲引擎同步
  • 所有節點可讀寫
  • 同步機制為同步
  • 存儲資訊價值量高

Replication

  • 弱一緻性
  • 速度快
  • 從節點不可寫入
  • 同步機制為異步
  • 存儲資訊價值量不高

這裡我們主要講下PXC,當你在一個節點進行相關操作,比如說插入一條資料、它會同步到其他節點,若所有節點同步成功則插入成功、若所有節點同步失敗,則復原并告知插入失敗,這個我們後面實踐一下就知道了。

建立MySQL叢集的步驟(PXC)

(一)、拉取鏡像并重命名

# 拉取鏡像
docker pull percona/percona-xtradb-cluster

# 重名名(這步也可以不做,我就是想後面少打點字)
docker tag percona/percona-xtradb-cluster:latest pxc:latest
           

(二)、組網

2.1、建立網絡:

指令:

docker network create mysql_net

示範:

⚡ root@ataola  ~  docker network create mysql_net
79885a1c3b8a783e096a1610df08e353641bda74d0b996b4200f2ea5db3c5dbd
 ⚡ root@ataola  ~  
           

2.2、檢視網絡:

指令:

docker network inspect mysql_net

示範:

⚡ root@ataola  ~  docker network inspect mysql_net
[
    {
        "Name": "mysql_net",
        "Id": "79885a1c3b8a783e096a1610df08e353641bda74d0b996b4200f2ea5db3c5dbd",
        "Created": "2020-05-30T21:26:53.852825919+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
 ⚡ root@ataola  ~  
           

(三)、建立資料卷

3.1、建立資料卷

指令:

docker volume create mysql_v

示範:

⚡ root@ataola  ~  docker volume create mysql_v1   
mysql_v1
 ⚡ root@ataola  ~  docker volume create mysql_v2
mysql_v2
 ⚡ root@ataola  ~  docker volume create mysql_v3
mysql_v3
 ⚡ root@ataola  ~  docker volume create mysql_v4
mysql_v4
 ⚡ root@ataola  ~  docker volume create mysql_v5
mysql_v5
 ⚡ root@ataola  ~  
           

3.2:檢視資料卷

指令:

docker volume inspect mysql_v

示範:

✘ ⚡ root@ataola  /home/caocao  docker volume inspect mysql_v1
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/mysql_v1/_data",
        "Name": "mysql_v1",
        "Options": {},
        "Scope": "local"
    }
]
 ⚡ root@ataola  /home/caocao  

           

(四)、建立MySQL節點

4.1、主節點:

指令:

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=studypxc -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=studymysql -v mysql_v1:/var/lib/mysql --privileged --name=mysql_node1 --net=mysql_net pxc

示範:

⚡ root@ataola  ~  docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=studypxc -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=studymysql -v mysql_v1:/var/lib/mysql --privileged --name=mysql_node1 --net=mysql_net pxc
09e7715f71b4411974d862a2aa74ed0b1018fc4efb4196707576f935e1425f6b
 ⚡ root@ataola  ~  docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                   NAMES
09e7715f71b4        pxc                 "/entrypoint.sh my..."   8 seconds ago       Up 6 seconds        0.0.0.0:3306->3306/tcp, 4567-4568/tcp   mysql_node1
 ⚡ root@ataola  ~ 
           

4.2、從節點:

指令:

docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=studypxc -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=studymysql -e CLUSTER_JOIN=mysql_node1 -v mysql_v2:/var/lib/mysql --privileged --name=mysql_node2 --net=mysql_net pxc

更改相關參數重複三次樓上操作,我們建構一個主節點外加四個從節點的mysql叢集,這個時候我們執行

docker ps -a

看下,可以看到它們都跑起來了。

⚡ root@ataola  ~  docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                   NAMES
8d809616ea08        pxc                 "/entrypoint.sh my..."   9 seconds ago       Up 8 seconds        4567-4568/tcp, 0.0.0.0:3310->3306/tcp   mysql_node5
6dc023253205        pxc                 "/entrypoint.sh my..."   18 seconds ago      Up 17 seconds       4567-4568/tcp, 0.0.0.0:3309->3306/tcp   mysql_node4
18c232855938        pxc                 "/entrypoint.sh my..."   53 seconds ago      Up 52 seconds       4567-4568/tcp, 0.0.0.0:3308->3306/tcp   mysql_node3
6de60216270a        pxc                 "/entrypoint.sh my..."   2 minutes ago       Up 2 minutes        4567-4568/tcp, 0.0.0.0:3307->3306/tcp   mysql_node2
09e7715f71b4        pxc                 "/entrypoint.sh my..."   10 minutes ago      Up 10 minutes       0.0.0.0:3306->3306/tcp, 4567-4568/tcp   mysql_node1
 ⚡ root@ataola  ~  
           

然後我們可以通過

docker network inspect mysql_net

檢視我們剛才建立叢集的網絡資訊

⚡ root@ataola  /home/caocao  docker network inspect mysql_net
[
    {
        "Name": "mysql_net",
        "Id": "79885a1c3b8a783e096a1610df08e353641bda74d0b996b4200f2ea5db3c5dbd",
        "Created": "2020-05-30T21:26:53.852825919+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "09e7715f71b4411974d862a2aa74ed0b1018fc4efb4196707576f935e1425f6b": {
                "Name": "mysql_node1",
                "EndpointID": "621bc0ec6e4adb78e72f0f78ca04d154029abe1f0bb91fc5ccd42156bfa32d52",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            },
            "0e4ef69c19b981163067ec8af0c38b6fa84c380855c22309a884f0a0ed691912": {
                "Name": "haproxy1",
                "EndpointID": "02e8c179fdb7cbc4b3e7d72f8412129da487c65a3897e70e0da5693aa0d8d500",
                "MacAddress": "02:42:ac:13:00:07",
                "IPv4Address": "172.19.0.7/16",
                "IPv6Address": ""
            },
            "18c232855938d7263b90a4ab88874676110c6197a601aa72d8bec8f52e73dd02": {
                "Name": "mysql_node3",
                "EndpointID": "010538caec3ab7aafe1c708ebebdffa43e268d68147cf4a60f86a77247b3ef86",
                "MacAddress": "02:42:ac:13:00:04",
                "IPv4Address": "172.19.0.4/16",
                "IPv6Address": ""
            },
            "6dc0232532057a65db0607c92517307ee480bec32cb6311d6615555482670c7a": {
                "Name": "mysql_node4",
                "EndpointID": "cc59fe8fc8d7d02f367ec75b1897c51bf3731dbc5dc8d70510dde34aee6d4afa",
                "MacAddress": "02:42:ac:13:00:05",
                "IPv4Address": "172.19.0.5/16",
                "IPv6Address": ""
            },
            "6de60216270a3b6f5bfbe5d94d40fa2449e443eb77b67d4bf005061dd4ff412e": {
                "Name": "mysql_node2",
                "EndpointID": "b674d25e3e6c999324de9704419b1c97f008ca6e5d27e825bc0fc61d600848ff",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "8d809616ea08d46a3febb95259d9d0672d6112dd8cbe6c29f03f49cbc44ef444": {
                "Name": "mysql_node5",
                "EndpointID": "01f0988019206e959a7099736d9995cec1676aaec360db9bd78fa61b68a87f71",
                "MacAddress": "02:42:ac:13:00:06",
                "IPv4Address": "172.19.0.6/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
 ⚡ root@ataola  /home/caocao  
           

至此,基于PXC解決方案MySQL叢集搭建已經完成了,當然這裡涉及到的一些指令和參數具體的還是要讀者去看樓下參考文獻的官方文檔的。

負載均衡(haproxy)

在樓上的例子中,我們建立了一個MySQL叢集,我們可以把它了解成一家超市。然後每個節點就是收銀台。這個時候就會有個問題了,假設那批去超市購物的人不太正常了,買完東西都擠到1号收銀台,那麼1号收銀台的收銀員她承受的壓力就會比較大,就會很焦慮。這個時候呢,超市經理拿這個大喇叭過來啊,你你你,去2号收銀台、你們去3号收銀台,購物的人很快地就付完錢回家了。haproxy就相當于這個超市經理,哪裡有空閑就排程往哪個節點去。

在了解完haproxy做的事情後,我們來實踐一番吧。

(一)、拉取鏡像

這裡我就不改名了,有興趣的童鞋自己對照pxc改個名字。

docker pull haproxy
           

(二)、建立haproxy配置檔案

這裡其他的配置都不用動,就後面server改成你電腦的配置

# 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
    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
           

(三)、建立haproxy容器

指令:

docker run -it -d -p 4001:8888 -p 4002:3306 -v /root/haproxy:/usr/local/etc/haproxy --name haproxy1 --privileged --net=mysql_net haproxy

這裡把監控界面的8888端口映射到主控端的4001,然後把資料庫負載均衡的3306端口映射到主控端的4002

示範:

⚡ root@ataola  ~/haproxy  docker run -it -d -p 4001:8888 -p 4002:3306 -v /root/haproxy:/usr/local/etc/haproxy --name haproxy1 --privileged --net=mysql_net haproxy
0e4ef69c19b981163067ec8af0c38b6fa84c380855c22309a884f0a0ed691912
 ⚡ root@ataola  ~/haproxy  
           

之後我們進入到這個起起來的容器

docker exec -it haproxy1 bash

執行配置指令:

haproxy -f /usr/local/etc/haproxy/haproxy.cfg

(四)、建立haproxy資料庫賬号

打開MySQL資料庫,建立一個使用者

CREATE USER \'haproxy\'@\'%\' IDENTIFIED BY \'superman\';

通路

http://localhost:4001/dbs

,就可以看到資料叢集的情況。

MySQL叢集搭建方案(PXC)

看到這裡就說明你的haproxy搭建成功了,接下來我們進行相關的實踐。

相關實驗

實驗須知

這裡我們在建立了一個test資料庫,在資料庫中建立一張資料表為user,并添加相應的字段和資料,具體的如下:

MySQL叢集搭建方案(PXC)

實驗一:在主節點和從節點都完好的情況下,分别向主節點和從節點插入資料,看看其他節點的變化。

主節點插入:

我們嘗試在主節點mysql_node1插入資料,然後去mysql_node_2去讀取資料,這裡我們就直接硬核的手動擋來吧(PS:初次加載時間長,如下圖)

MySQL叢集搭建方案(PXC)

可以看到我們從mysql_node2節點讀取到了mysql_node1主節點寫入的内容。

從節點插入:

把樓上的例子反過來,這次我們從節點插入,主節點讀取看看。

MySQL叢集搭建方案(PXC)

從這個實驗,我們可以印證一點的是,主從節點都是可以讀寫的。

實驗二:挂掉主節點,從節點看能不能插入

接下來我們就要開始搞事情了,把主節點停掉,再從節點插入資料看看。

指令:

docker pause mysql_node1

示範:

MySQL叢集搭建方案(PXC)

這個時候主節點是打不開的,相當于當機了。

MySQL叢集搭建方案(PXC)
MySQL叢集搭建方案(PXC)

我們嘗試着在從節點插入資料,發現從節點也是打不開的

MySQL叢集搭建方案(PXC)

這印證了上面說的強一緻性,同步機制為同步, 當主節點挂了以後,其餘節點不可讀寫。

實驗三:挂掉某個從節點,看看主從節點能否插入

我們把node3和node4服務給停掉,接着我們嘗試着打開node1去插入一條張東升試試

MySQL叢集搭建方案(PXC)
MySQL叢集搭建方案(PXC)

可以看到在主節點插入資料,從節點也能夠同步。

接着我們在node2從節點插入張朝陽

MySQL叢集搭建方案(PXC)

可以看到從節點插入成功,也同步到了主節點。

這個時候,我們把node3和node4起起來,看下資料會不會進行一個同步

MySQL叢集搭建方案(PXC)

可以看到,當node3和node4恢複的時候,便會進行一個資料同步,我們便在node3和node4中看到了張東升和張朝陽。

參考文獻

percona介紹:https://hub.docker.com/_/percona

percona安裝:https://www.percona.com/doc/percona-server/8.0/installation/docker.html

Docker環境下的前後端分離項目部署與運維: https://coding.imooc.com/class/219.html

最後

寫到這裡,筆者也隻是記流水賬一樣,記錄了當時的操作過程并加以複現,并沒有對叢集關于性能熱備份冷備份等等方面進行深入探讨學習,這裡僅作抛磚引玉,有興趣的童鞋接力實踐吧!

MySQL叢集搭建方案(PXC)

本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協定進行許可。