MySQL 資料庫叢集-PXC 方案(二)
MySQL 資料庫叢集-PXC 方案(二)
叢集狀態資訊
PXC 叢集資訊可以分為佇列資訊、複製資訊、流控資訊、事務資訊、狀態資訊。這些資訊可以通過 SQL 查詢到。每種資訊的詳細意義可以在官網檢視。
show status like '%wsrep%';
複製資訊
舉例說明幾個重要的資訊:
狀態 | 描述 |
---|---|
wsrep_replicated | 被其他節點複製的次數 |
wsrep_replicated_bytes | 被其他節點複製的資料次數 |
wsrep_received | 從其他節點處收到的寫入請求總數 |
wsrep_received_bytes | 從其他節點處收到的寫入資料總數 |
wsrep_last_applied | 同步應用次數 |
wsrep_last_committed | 事務提交次數 |
佇列資訊
佇列是一種很好的快取機制,如果 PXC 正在滿負荷工作,沒有執行緒去執行資料的同步,同步請求會快取到佇列中,然後空閒執行緒從佇列中取出任務,執行同步的請求,有了佇列 PXC 就能用少量的執行緒應對瞬時大量的同步請求。
狀態 | 描述 |
---|---|
wsrep_local_send_queue | 傳送佇列的長度(瞬時同步的請求數量) |
wsrep_local_send_queue_max | 傳送佇列的最大長度 |
wsrep_local_send_queue_min | 傳送佇列的最小長度 |
wsrep_local_send_queue_avg | 傳送佇列的平均長度 |
wsrep_local_recv_queue | 接收佇列的長度 |
wsrep_local_recv_queue_max | 接收佇列的最大長度 |
wsrep_local_recv_queue_min | 接收佇列的最小長度 |
wsrep_local_recv_queue_avg | 接收佇列的平均長度 |
當傳送佇列的平均長度(wsrep_local_send_queue_avg)
值很大,傳送佇列的長度(wsrep_local_send_queue)
也很大的時候,說明 PXC 叢集同步資料的速度已經很慢了,佇列裡邊積壓了大量的同步請求,這個時候就要檢查一下網速是不是正常,或者同步的執行緒數量是不是太少。
當接收佇列的平均長度(wsrep_local_recv_queue_avg)
接收佇列的長度(wsrep_local_recv_queue)
也很大的時候,這說明本地沒有足夠的執行緒去執行持久化的操作,增加執行緒就可以解決這個問題。
流量控制資訊
流量控制就是 PXC 叢集在同步速度較慢的情況下,為了避免同步速度跟不上寫入速度而推出的一種限速機制,就是限制資料的寫入,直到同步佇列的長度變小,同步速度變快為止,才會解除流量控制。流量控制的後果很嚴重,而且一個很小的操作就會引發流量控制。
狀態 | 說明 |
---|---|
wsrep_flow_control_paused_ns | 流控暫停狀態下花費的總時間(納秒) |
wsrep_flow_control_paused | 流量控制暫停時間的佔比(0~1) |
wsrep_flow_control_sent | 傳送的流控暫停事件的數量 |
wsrep_flow_control_recv | 接收的流控暫停事件的數量 |
wsrep_flow_control_interval | 流量控制的下限和上限。上限是佇列中允許的最大請求數。如果佇列達到上限,則拒絕新的請求。當處理現有請求時,佇列會減少,一旦到達下限,將再次允許新的請求 |
wsrep_flow_control_status | 流量控制狀態 OFF:關閉 0N: 開啟 |
流控的主要原因節點之間同步的速度慢,佇列積壓了大量的請求,這才是流控的主要原因。
流控解決辦法:
- 改善網速,提高頻寬,更換交換機,千兆網絡卡更換成萬兆網絡卡
- 增加執行緒,執行緒多了執行的速度也就快了。佇列裡邊就不會積壓大量的請求
- 提升硬體效能,比如升級 CPU,記憶體以及更換光纖硬碟等等都可以提高寫入速度
第一項和第三項屬於更換硬體的方法,主要說一下第二個方法增加執行緒數提升同步速度。在 PXC 的配置檔案加上wsrep_slave_threads
引數。代表的是本地執行佇列的執行緒數量,一般這個數是 CPU 執行緒數的 1-1.5 倍。比如伺服器 CPU 是 8 核 16 執行緒的,這裡就可以寫 16-24 就可以。
wsrep_slave_threads=16
節點與叢集的狀態資訊
狀態 | 說明 |
---|---|
wsrep_local_state_comment | 節點狀態 |
wsrep_cluster_status | 叢集狀態(Primary:正常狀態、Non-Primary:出現了腦裂請求、Disconnected:不能提供服務,出現宕機) |
wsrep_connected | 節點是否連線到叢集 |
wsrep_ready | 叢集是否正常工作 |
wsrep_cluster_size | 節點數量 |
wsrep_desync_count | 延時節點數量 |
wsrep_incoming_addresses | 叢集節點 IP 地址 |
事務相關資訊
狀態 | 說明 |
---|---|
wsrep_cert_deps_distance | 事務執行併發數 |
wsrep_apply_oooe | 接收佇列中事務的佔比 |
wsrep_apply_oool | 接收佇列中事務亂序執行的頻率 |
wsrep_apply_window | 接收佇列中事務的平均數量 |
wsrep_commit_oooe | 傳送佇列中事務的佔比 |
wsrep_commit_oool | 無任何意義,不存在本地的亂序提交 |
wsrep_commit_window | 傳送佇列中事務的平均數量 |
PXC 節點的安全下線操作
節點用什麼命令啟動,就用對應的關閉命令去關閉。
- 主節點的管理命令(第一個啟動的 PXC 節點)
systemctl start [email protected]
systemctl stop [email protected]
systemctl restart [email protected]
- 非主節點的管理命令(非第一個啟動的 PXC 節點)
service mysql start
service mysql stop
service mysql restart
- 如果最後關閉的 PXC 節點是安全退出的,那麼下次啟動要最先啟動這個節點,而且要以主節點啟動。
- 如果最後關閉的 PXC 節點不是安全退出的,那麼要先修改
/var/lib/mysql/grastate.dat
檔案,把其中的safe_to_bootstrap
屬性值設定為 1,再按照主節點啟動。
意外下線部分節點
安全下線節點不會讓剩下的節點宕機,如果節點意外退出,叢集的規模不會縮小,意外退出的節點超過半數,比如三個節點意外退出了 2 個節點,那麼剩下的節點就不能夠讀寫了。其他節點按照普通節點啟動上線即可恢復 pxc 叢集。
意外下線全部節點,不同時退出
如果三個節點都意外退出,那麼檢視/var/lib/mysql/grastate.dat
檔案,看看哪個檔案的safe_to_bootstarp
的值是 1,那麼那個節點是最後意外關閉的,再按照safe_to_bootstarp
的值啟動 pxc 叢集。
意外下線全部節點,同時退出
如果三個節點同時意外退出,我們需要修改配置檔案,挑選一個節點作為主節點,修改safe_to_bootstarp
的值設定為 1,那麼這個節點可以以主節點啟動。
配置 MyCat 負載均衡
準備工作(一)
我們需要建立兩個 PXC 叢集,充當兩個分片。
上文中已經創建出來了一個分片,參考步驟然後創建出來第二個分片。
最後會有 6 個 centos 虛擬機器。
我的第一個如下:
- 主:192.168.3.137
- 從:192.168.3.138
- 從:192.168.3.139
我的第二個如下:
- 主:192.168.3.141
- 從:192.168.3.143
- 從:192.168.3.144
MyCat : 192.168.3.146
準備工作(二)
在 192.168.3.146 Centos 伺服器上進行如下操作:
由於 MyCat 是依賴 jdk 的所以我們先安裝 jdk 環境。
yum install -y java-1.8.0-openjdk-devel.x86_64
配置 JAVA_HOME 環境變數
ls -lrt /etc/alternatives/java
vim /etc/profile
source /etc/profile
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10-1.el7_9.x86_64/
輸入 java -version 如下圖就完成配置。
準備工作(三)
下載 mycat
http://dl.mycat.org.cn/1.6.5/
上傳 MyCat 壓縮包到虛擬機器,並解壓。
開放防火牆 8066 和 9066 埠:
firewall-cmd --zone=public --add-port=8066/tcp --permanent
firewall-cmd --zone=public --add-port=9066/tcp --permanent
firewall-cmd --reload
關閉 SELINUX
vim /etc/selinux/config
把 SELINUX 屬性值設定成 disabled,之後儲存。重啟。
reboot
修改 MyCat 的 bin 目錄中所有.sh 檔案的許可權:
chmod -R 777 ./*.sh
MyCat 啟動與關閉
啟動MyCat:
./mycat start
檢視啟動狀態:
./mycat status
停止:
./mycat stop
重啟:
./mycat restart
準備工作(四)
修改配置檔案:
修改 server.xml 檔案,設定 MyCat 帳戶和虛擬邏輯庫
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
<system>
<property name="nonePasswordLogin">0</property>
<property name="useHandshakeV10">1</property>
<property name="useSqlStat">0</property>
<property name="useGlobleTableCheck">0</property>
<property name="sequnceHandlerType">2</property>
<property name="subqueryRelationshipCheck">false</property>
<property name="processorBufferPoolType">0</property>
<property name="handleDistributedTransactions">0</property>
<property name="useOffHeapForMerge">1</property>
<property name="memoryPageSize">64k</property>
<property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<property name="systemReserveMemorySize">384m</property>
<property name="useZKSwitch">false</property>
</system>
<!--這裡是設定的admin使用者和虛擬邏輯庫-->
<user name="admin" defaultAccount="true">
<property name="password">Abc_123456</property>
<property name="schemas">test</property>
</user>
</mycat:server>
修改 schema.xml 檔案,設定資料庫連線和虛擬資料表
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!--配置資料表-->
<schema name="test" checkSQLschema="false" sqlMaxLimit="100">
<table name="t_user" dataNode="dn1,dn2" rule="mod-long" />
</schema>
<!--配置分片關係-->
<dataNode name="dn1" dataHost="cluster1" database="test" />
<dataNode name="dn2" dataHost="cluster2" database="test" />
<!--配置連線資訊-->
<dataHost name="cluster1" maxCon="1000" minCon="10" balance="2"
writeType="1" dbType="mysql" dbDriver="native" switchType="1"
slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="W1" url="192.168.3.137:3306" user="admin"
password="Abc_123456">
<readHost host="W1R1" url="192.168.3.138:3306" user="admin"
password="Abc_123456" />
<readHost host="W1R2" url="192.168.3.139:3306" user="admin"
password="Abc_123456" />
</writeHost>
<writeHost host="W2" url="192.168.3.138:3306" user="admin"
password="Abc_123456">
<readHost host="W2R1" url="192.168.3.137:3306" user="admin"
password="Abc_123456" />
<readHost host="W2R2" url="192.168.3.139:3306" user="admin"
password="Abc_123456" />
</writeHost>
</dataHost>
<dataHost name="cluster2" maxCon="1000" minCon="10" balance="2"
writeType="1" dbType="mysql" dbDriver="native" switchType="1"
slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="W1" url="192.168.3.141:3306" user="admin"
password="Abc_123456">
<readHost host="W1R1" url="192.168.3.143:3306" user="admin"
password="Abc_123456" />
<readHost host="W1R2" url="192.168.3.144:3306" user="admin"
password="Abc_123456" />
</writeHost>
<writeHost host="W2" url="192.168.3.143:3306" user="admin"
password="Abc_123456">
<readHost host="W2R1" url="192.168.3.141:3306" user="admin"
password="Abc_123456" />
<readHost host="W2R2" url="192.168.3.144:3306" user="admin"
password="Abc_123456" />
</writeHost>
</dataHost>
</mycat:schema>
修改 rule.xml 檔案,把 mod-long 的 count 值修改成 2
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<property name="count">2</property>
</function>
重啟 MyCat。
測試
在兩個分片中都建立 t_user 表:
CREATE TABLE t_user(
id INT UNSIGNED PRIMARY KEY,
username VARCHAR(200) NOT NULL,
password VARCHAR(2000) NOT NULL,
tel CHAR(11) NOT NULL,
locked TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
INDEX idx_username(username) USING BTREE,
UNIQUE INDEX unq_username(username) USING BTREE
);
遠端連線 mycat。
向 t_user 表寫入資料,感受資料的切分。
USE test;
select * from t_user;
#第一條記錄被切分到第二個分片
INSERT INTO t_user(id,username,password,tel,locked) VALUES(1,"Jack",HEX(AES_ENCRYPT('123456','HelloWorld')),'1333222111',false);
#第二條記錄被切分到第一個分片
INSERT INTO t_user(id,username,password,tel,locked) VALUES(2,"Rose",HEX(AES_ENCRYPT('123456','HelloWorld')),'1335555111',false);
可以檢視對應的庫中都是沒有問題的。
資料切分
切分演算法 | 適用場合 | 備註 |
---|---|---|
主鍵求模切分 | 資料增長緩慢,難於增加分片 | 有明確主鍵值 |
列舉值切分 | 歸類儲存資料,適用於大多數業務 | |
主鍵範圍切分 | 資料快速增長,容易增加分片 | 有明確主鍵值 |
日期切分 | 資料快速增長,容易增加分片 |
主鍵求模切分
上面的示例中,使用的就是主鍵求模切分,其特點如下:
- 主鍵求模切分適合用在初始資料很大,但是資料增長不快的場景。例如,地圖產品、行政資料、企業資料等。
- 主鍵求模切分的弊端在於擴充套件新分片難度大,遷移的資料太多。
- 如果需要擴充套件分片數量,建議擴充套件後的分片數量是原有分片的 2n 倍。例如,原本是兩個分片,擴充套件後是四個分片。
主鍵範圍切分
- 主鍵範圍切分適合用在資料快速增長的場景。
- 容易增加分片,需要有明確的主鍵列。
日期切分
- 日期切分適合用在資料快速增長的場景。
- 容易增加分片,需要有明確的日期列。
列舉值切分
- 列舉值切分適合用在歸類儲存資料的場景,適合大多數業務。
- 列舉值切分按照某個欄位的值(數字)與
mapFile
配置的對映關係來切分資料。 - 列舉值切分的弊端在於分片儲存的資料不夠均勻。
在rule.xml
中增加配置如下:
<!-- 定義分片規則 -->
<tableRule name="sharding-customer">
<rule>
<!-- 定義使用哪個列作為分片列 -->
<columns>sharding_id</columns>
<algorithm>customer-hash-int</algorithm>
</rule>
</tableRule>
<!-- 定義分片演算法 -->
<function name="customer-hash-int"
class="io.mycat.route.function.PartitionByFileMap">
<!-- 定義mapFile的檔名,位於conf目錄下 -->
<property name="mapFile">customer-hash-int.txt</property>
</function>
在conf
目錄下建立customer-hash-int.txt
檔案,定義區號與分片索引的對應關係:0 代表第一個分片,1 代表第二個分片。
101=0
102=0
103=0
104=1
105=1
106=1
配置schema.xml
,增加一個邏輯表,並將其分片規則設定為sharding-customer
:
<schema name="test" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
<table name="t_user" dataNode="dn1,dn2" rule="mod-long"/>
<table name="t_customer" dataNode="dn1,dn2" rule="sharding-customer"/>
</schema>
進入 MyCat 中執行熱載入語句,該語句的作用可以使 Mycat 不用重啟就能應用新的配置:
reload @@config_all;
在兩個分片中分別執行如下建表語句:
USE test;
CREATE TABLE t_customer(
id INT UNSIGNED PRIMARY KEY,
username VARCHAR(200) NOT NULL,
sharding_id INT NOT NULL
);
之後我們在 MyCat 中進行查詢看看:
也是 ok 的。
接著我們增加一條資料:
insert into t_customer(id,username,sharding_id) values (1,'Michelle',101);
insert into t_customer(id,username,sharding_id) values (2,'Jack',102);
檢視第一個分片可以看到資料已經切分過來了
如果我們再增加一條 SQL:
insert into t_customer(id,username,sharding_id) values (3,'Smith',105);
很顯然,資料被分到了第二個分片中。
父子表
當有關聯的資料儲存在不同的分片時,就會遇到表連線的問題,在 MyCat 中是不允許跨分片做表連線查詢的。為了解決跨分片表連線的問題,MyCat 提出了父子表這種解決方案。
父子表規定父表可以有任意的切分演算法,但與之關聯的子表不允許有切分演算法,即子表的資料總是與父表的資料儲存在一個分片中。父表不管使用什麼切分演算法,子表總是跟隨著父表儲存。
例如,使用者表與訂單表是有關聯關係的,我們可以將使用者表作為父表,訂單表作為子表。當 A 使用者被儲存至分片 1 中,那麼 A 使用者產生的訂單資料也會跟隨著儲存在分片 1 中,這樣在查詢 A 使用者的訂單資料時就不需要跨分片了。如下圖所示:
配置父子表
在t_customer
中增加 childTable。需要注意的是一個 table 可以有多個 childTable。
<table name="t_customer" dataNode="dn1,dn2" rule="sharding-customer">
<childTable name="t_orders" primaryKey="ID" joinKey="customer_id" parentKey="id"/>
</table>
進入 MyCat 中執行熱載入語句,該語句的作用可以使 Mycat 不用重啟就能應用新的配置:
reload @@config_all;
在兩個分片中執行建表 SQL:
USE test;
CREATE TABLE t_orders(
id INT UNSIGNED PRIMARY KEY,
customer_id INT NOT NULL,
datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
執行成功後,我們插入些資料測試:
USE test;
insert into t_orders(id,customer_id) values (1,1);
insert into t_orders(id,customer_id) values (2,1);
insert into t_orders(id,customer_id) values (3,1);
insert into t_orders(id,customer_id) values (4,2);
insert into t_orders(id,customer_id) values (5,3);
我們在第一個分片中增加了兩個使用者 id 為 1 、2 的,在第二個分片中增加了一個使用者 id 為 3 的。
所以第一個分片會有 4 條記錄,而第二個分片中有一條。
由於父子表的資料都是儲存在同一個分片,所以在 MyCat 上進行關聯查詢也是沒有問題的:
組建雙機熱備的高可用 MyCat 叢集
在之前的示例中,我們可以看到對後端資料庫叢集的讀寫操作都是在 MyCat 上進行的。MyCat 作為一個負責接收客戶端請求,並將請求轉發到後端資料庫叢集的中介軟體,不可避免的需要具備高可用性。否則,如果 MyCat 出現單點故障,那麼整個資料庫叢集也就無法使用了,這對整個系統的影響是十分巨大的。
所以我們現在將要演示如何去構建一個高可用的 MyCat 叢集,為了搭建 MyCat 高可用叢集,除了要有兩個以上的 MyCat 節點外,還需要引入 Haproxy 和 Keepalived 元件。
其中 Haproxy 作為負載均衡元件,位於最前端接收客戶端的請求並將請求分發到各個 MyCat 節點上,用於保證 MyCat 的高可用。而 Keepalived 則用於實現雙機熱備,因為 Haproxy 也需要高可用,當一個 Haproxy 宕機時,另一個備用的 Haproxy 能夠馬上接替。也就說同一時間下只會有一個 Haproxy 在執行,另一個 Haproxy 作為備用處於等待狀態。當正在執行中的 Haproxy 因意外宕機時,Keepalived 能夠馬上將備用的 Haproxy 切換到執行狀態。
Keepalived 是讓主機之間爭搶同一個虛擬 IP(VIP)來實現高可用的,這些主機分為 Master 和 Backup 兩種角色,並且 Master 只有一個,而 Backup 可以有多個。最開始 Master 先獲取到 VIP 處於執行狀態,當 Master 宕機後,Backup 檢測不到 Master 的情況下就會自動獲取到這個 VIP,此時傳送到該 VIP 的請求就會被 Backup 接收到。這樣 Backup 就能無縫接替 Master 的工作,以實現高可用。
引入這些元件後,最終我們的叢集架構將演變成這樣子:
Haproxy包括以下一些特徵:
- 根據靜態分配的cookie分配HTTP請求。
- 分配負載到各個伺服器,同時保證伺服器通過使用HTTP Cookie實現連線保持。
- 當主伺服器宕機時切換到備伺服器,允許特殊埠的服務監控。
- 做維護時通過配置可以保證業務的連續性,更加人性化。
- 新增修改刪除HTTP Request和Respone頭。
- 通過特定表示式Block HTTP請求。
- 根據應用的cookie做連線保持。
- 常有使用者驗證的詳細的HTML監控報告。
Haproxy的負載均衡演算法現在具體有如下8種:
- roundrobin:簡單的輪詢。
- static-rr:權重輪詢。
- leastconn:最少連線者優先。
- source:根據請求源IP,這個跟Nginx的ip_hash機制類似。
- ri:根據請求的URI。
- rl_param:表示根據請求的URI引數。
- hdr(name):根據HTTP請求頭來鎖定每一次HTTP請求。
- rdp-cookie(name):根據cookie來鎖定並雜湊每一次TCP請求。
這裡就不再演示如何搭建第二臺 Mycat 環境了。
這裡再說一下目前我的叢集:
第一個 PXC 分片:
- 主:192.168.3.137
- 從:192.168.3.138
- 從:192.168.3.139
第二個 PXC 分片:
- 主:192.168.3.141
- 從:192.168.3.143
- 從:192.168.3.144
第一臺 MyCat : 192.168.3.146
第二臺 MyCat: 192.168.3.147
安裝 Haproxy
由於我電腦只有 8G 記憶體,有點吃不消所以我的 Haproxy 都在 Mycat 伺服器上。
開放防火牆 3306 和 4001 埠:
埠 | 作用 |
---|---|
3306 | TCP/IP 轉發埠 |
4001 | 監控介面埠 |
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --zone=public --add-port=4001/tcp --permanent
firewall-cmd --reload
關閉 SELINUX
vim /etc/selinux/config
把 SELINUX 屬性值設定成 disabled,之後儲存。重啟。
reboot
接著我們安裝 haproxy
yum install -y haproxy
安裝完成後我們修改對應的配置檔案
vim /etc/haproxy/haproxy.cfg
記得修改為自己的 MyCat 的 IP。
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
listen admin_stats
# 繫結的ip及監聽的埠
bind 0.0.0.0:4001
# 訪問協議
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
# 負載均衡演算法
balance roundrobin
#日誌格式
option tcplog
# 需要被負載均衡的主機
server mycat_1 192.168.3.146:8066 check port 8066 weight 1 maxconn 2000
server mycat_2 192.168.3.147:8066 check port 8066 weight 1 maxconn 2000
#使用keepalive檢測死鏈
option tcpka
配置完成之後我們進行啟動
service haproxy start
我們在瀏覽器輸入 IP 測試:
http://192.168.3.146:4001/dbs
輸入我們配置的賬號密碼後就可以看到如下圖:
Haproxy 的監控介面提供的監控資訊也比較全面,在該介面下,我們可以看到每個主機的連線資訊及其自身狀態。當主機無法連線時,Status
一欄會顯示DOWN
,並且背景色也會變為紅色。正常狀態下的值則為UP
,背景色為綠色。
另一個 Haproxy 節點也是使用以上的步驟進行安裝和配置,這裡就不再重複了。
測試 Haproxy
我們遠端連線一下試試:
可以發現新增都是沒有問題的。
我們搭建 Haproxy 是為了讓 MyCat 具備高可用的,所以最後測試一下 MyCat 是否已具備有高可用性,我們將 147 的 MyCat 停掉。
此時,從 Haproxy 的監控介面中,可以看到mycat_2
這個節點已經處於下線狀態了:
接著我們再去增加一條資料試試。
從測試結果可以看到,插入和查詢語句依舊是能正常執行的。也就是說即便此時關掉一個 MyCat 節點整個資料庫叢集還能夠正常使用,說明現在 MyCat 叢集是具有高可用性了。
利用 Keepalived 實現 Haproxy 的高可用
實現了 MyCat 叢集的高可用之後,我們還得實現 Haproxy 的高可用,因為現在的架構已經從最開始的 MyCat 面向客戶端變為了 Haproxy 面向客戶端。
而同一時間只需要存在一個可用的 Haproxy,否則客戶端就不知道該連哪個 Haproxy 了。這也是為什麼要採用 VIP 的原因,這種機制能讓多個節點互相接替時依舊使用同一個 IP,客戶端至始至終只需要連線這個 VIP。所以實現 Haproxy 的高可用就要輪到 Keepalived 出場了。
先開啟防火牆的 VRRP 協議:
#開啟VRRP
firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --protocol vrrp -j ACCEPT
#應用設定
firewall-cmd --reload
安裝 Keepalived
yum install -y keepalived
編輯配置檔案
vim /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
state MASTER
interface enp0s3
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.3.177
}
}
配置說明:
state MASTER
:定義節點角色為 master,當角色為 master 時,該節點無需爭搶就能獲取到 VIP。叢集內允許有多個 master,當存在多個 master 時,master 之間就需要爭搶 VIP。為其他角色時,只有 master 下線才能獲取到 VIPinterface ens32
:定義可用於外部通訊的網絡卡名稱,網絡卡名稱可以通過ip addr
命令檢視virtual_router_id 51
:定義虛擬路由的 id,取值在 0-255,每個節點的值需要唯一,也就是不能配置成一樣的priority 100
:定義權重,權重越高就越優先獲取到 VIPadvert_int 1
:定義檢測間隔時間為 1 秒authentication
:定義心跳檢查時所使用的認證資訊auth_type PASS
:定義認證型別為密碼auth_pass 123456
:定義具體的密碼
virtual_ipaddress
:定義虛擬 IP(VIP),需要為同一網段下的 IP,並且每個節點需要一致
完成以上配置後,啟動 keepalived 服務:
service keepalived start
我們 ping 一下我們的虛擬地址試試,也是 OK 的!
另外一臺步驟一模一樣,這裡就不演示了!
測試 Keepalived
以上我們完成了 Keepalived 的安裝與配置,最後我們來測試 Haproxy 是否已具有高可用性。
連線成功後,執行一些語句測試能否正常插入、查詢資料:
最後測試一下 Haproxy 的高可用性,將其中一個 Haproxy 節點上的 keepalived 服務給關掉。
service keepalived stop
然後再次執行執行一些語句測試能否正常插入、查詢資料,如下能正常執行代表 Haproxy 節點已具有高可用性:
大功告成!
歡迎關注我的公眾號:Java菜鳥程式設計師
希望可以一起探討交流,一起學習!