伺服器快過期了,清一點庫存,把運維這塊的知識複習下
為什麼要搭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
,就可以看到資料叢集的情況。
看到這裡就說明你的haproxy搭建成功了,接下來我們進行相關的實踐。
相關實驗
實驗須知
這裡我們在建立了一個test資料庫,在資料庫中建立一張資料表為user,并添加相應的字段和資料,具體的如下:
實驗一:在主節點和從節點都完好的情況下,分别向主節點和從節點插入資料,看看其他節點的變化。
主節點插入:
我們嘗試在主節點mysql_node1插入資料,然後去mysql_node_2去讀取資料,這裡我們就直接硬核的手動擋來吧(PS:初次加載時間長,如下圖)
可以看到我們從mysql_node2節點讀取到了mysql_node1主節點寫入的内容。
從節點插入:
把樓上的例子反過來,這次我們從節點插入,主節點讀取看看。
從這個實驗,我們可以印證一點的是,主從節點都是可以讀寫的。
實驗二:挂掉主節點,從節點看能不能插入
接下來我們就要開始搞事情了,把主節點停掉,再從節點插入資料看看。
指令:
docker pause mysql_node1
示範:
這個時候主節點是打不開的,相當于當機了。
我們嘗試着在從節點插入資料,發現從節點也是打不開的
這印證了上面說的強一緻性,同步機制為同步, 當主節點挂了以後,其餘節點不可讀寫。
實驗三:挂掉某個從節點,看看主從節點能否插入
我們把node3和node4服務給停掉,接着我們嘗試着打開node1去插入一條張東升試試
可以看到在主節點插入資料,從節點也能夠同步。
接着我們在node2從節點插入張朝陽
可以看到從節點插入成功,也同步到了主節點。
這個時候,我們把node3和node4起起來,看下資料會不會進行一個同步
可以看到,當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
最後
寫到這裡,筆者也隻是記流水賬一樣,記錄了當時的操作過程并加以複現,并沒有對叢集關于性能熱備份冷備份等等方面進行深入探讨學習,這裡僅作抛磚引玉,有興趣的童鞋接力實踐吧!
本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協定進行許可。