業務不斷地在增加,集羣分片中的數據也會隨着時間的推移而增長,其中有至關一部分的數據是不多被使用的,例如幾年前的訂單記錄、交易記錄、商品評論等數據。這部分數據就稱之爲冷數據,與之相反常常被使用的數據則稱之爲熱數據。node
咱們都知道當MySQL的單表數據量超過兩千萬時,讀寫性能就會急劇降低。若是其中存儲的大部分都是高價值的熱數據還好說,能夠花費資金去擴展集羣分片,由於這些數據能夠帶來收益。但若是是低價值的冷數據,就不必去花這個錢了。mysql
因此咱們要將冷數據從集羣分片中剝離出來,存儲至專門的歸檔數據庫中,以騰出存儲空間、減輕集羣分片的存儲壓力。讓集羣分片儘可能只存儲熱數據,維持一個較好的讀寫性能,而沒必要浪費存儲空間在冷數據上:
算法
在歸檔數據庫上不適合使用InnoDB引擎,由於InnoDB的瞬時寫入性能不高。一般會採用Percona出品的TokuDB做爲歸檔數據庫的存儲引擎。由於該引擎具備以下特色:sql
上一小節介紹了冷熱數據分離的概念,本小節咱們來搭建一個用於歸檔冷數據的高可用Replication集羣。雖然是歸檔庫,但也得讓其具備高可用性,畢竟在實際的企業中是不容許數據庫出現單點故障的。並且歸檔庫中的數據也不是不會被使用到,只不過是使用概率不高而已。數據庫
本文中的Replication集羣架構設計以下:
vim
所謂Replication集羣就是咱們常說的主從架構,在Replication集羣中,節點分爲Master和Slave兩種角色。Master主要是提供寫服務,Slave則提供讀服務,而且一般Slave會被設置爲read_only
。後端
主從節點之間的數據同步是異步進行的,Slave使用一個線程監聽Master節點的binlog
日誌,當Master的binlog
日誌發生變化時,該線程就會讀取Master的binlog
日誌內容並寫入到本地的relay_log
中。而後mysql進程會定時讀取relay_log
並將數據寫入到本地的binlog
文件,這樣就實現了主從之間的數據同步。以下圖所示:
瀏覽器
爲了保證Replication集羣的高可用,咱們須要讓兩個數據庫節點之間互爲主從關係,實現雙向的數據同步。這樣才能在主節點掛掉時進行主從切換,不然主節點在恢復後不會向從節點同步數據,會致使節點之間的數據不一致:
bash
接下來開始準備集羣搭建的前置環境,首先須要建立4臺虛擬機,其中兩臺安裝Percona Server作Replication集羣,兩臺安裝Haproxy和Keepalived作負載均衡和雙機熱備:服務器
角色 | Host | IP |
---|---|---|
Haproxy+Keepalived | HA-01 | 192.168.190.135 |
Haproxy+Keepalived | HA-02 | 192.168.190.143 |
Percona Server | node-A | 192.168.190.142 |
Percona Server | node-B | 192.168.190.131 |
每臺虛擬機的配置以下:
環境版本說明:
以前說了InnoDB由於其特性不適合做爲歸檔數據庫的存儲引擎,而應採用TokuDB。TokuDB能夠安裝在任意MySQL的衍生版本上,本文采用的是Percona Server這個MySQL衍生版做爲演示。
我這裏已經事先在192.168.190.142
和192.168.190.131
兩個虛擬機上安裝好了Percona Server,如不瞭解其安裝方式的話,可參考:安裝Percona Server數據庫(in CentOS 8)。接下來,咱們就開始爲Percona Server安裝TokuDB。
首先,在安裝TokuDB前確保系統中已有jemalloc庫,沒有的話可使用以下命令安裝:
[root@node-A ~]# yum install -y jemalloc [root@node-A ~]# ls /usr/lib64/ |grep jemalloc # 庫文件所在路徑 libjemalloc.so.1 [root@node-A ~]#
在配置文件中添加jemalloc庫文件所在路徑的配置:
[root@node-A ~]# vim /etc/my.cnf ... [mysql_safe] malloc-lib=/usr/lib64/libjemalloc.so.1
完成配置文件的修改後,重啓數據庫服務:
[root@node-A ~]# systemctl restart mysqld
爲了保證TokuDB的寫入性能,咱們須要調整一下Linux系統的大頁內存管理的設置,命令以下:
# 採用動態分配內存而不是預先分配內存 [root@node-A ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled # 開啓內存的碎片整理 [root@node-A ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
經過官方提供的yum
倉庫安裝TokuDB引擎:
[root@node-A ~]# yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm [root@node-A ~]# percona-release setup ps80 [root@node-A ~]# yum install -y percona-server-tokudb.x86_64
接着使用ps-admin
命令將TokuDB引擎安裝到MySQL上:
[root@node-A ~]# ps-admin --enable-tokudb -uroot -p
重啓數據庫服務:
[root@node-A ~]# systemctl restart mysqld
數據庫重啓完成後,再執行一次ps-admin
命令以激活TokuDB引擎:
[root@node-A ~]# ps-admin --enable-tokudb -uroot -p
最後使用show engines;
語句驗證一下MySQL上是否已成功安裝了TokuDB引擎:
首先在兩個節點上分別建立用於同步的數據庫帳戶:
create user 'backup'@'%' identified by 'Abc_123456'; grant super, reload, replication slave on *.* to 'backup'@'%'; flush privileges;
而後修改MySQL配置文件:
[root@node-A ~]# vim /etc/my.cnf [mysqld] # 設置節點的id server_id=101 # 開啓binlog log_bin=mysql_bin # 開啓relay_log relay_log=relay_bin
另一個節點也是一樣的配置,只不過server_id
不能是同樣的:
[root@node-B ~]# vim /etc/my.cnf [mysqld] server_id=102 log_bin=mysql_bin relay_log=relay_bin
修改完配置文件後,重啓MySQL服務:
[root@node-A ~]# systemctl restart mysqld [root@node-B ~]# systemctl restart mysqld
node-B
對node-A
的主從關係進入node-B
的MySQL命令行終端,分別執行以下語句:
mysql> stop slave; -- 中止主從同步 mysql> change master to master_host='192.168.190.142', master_port=3306, master_user='backup', master_password='Abc_123456'; -- 配置Master節點的鏈接信息 mysql> start slave; -- 啓動主從同步
使用show slave status\G;
語句查看主從同步狀態,Slave_IO_Running
和Slave_SQL_Running
的值均爲Yes
才能表示主從同步狀態是正常的:
node-A
對node-B
的主從關係爲了實現雙向同步,node-A
和node-B
須要互爲主從關係,因此還須要配置node-A
對node-B
的主從關係。進入node-A
的MySQL命令行終端,分別執行以下語句,注意這裏的master_host
須要爲node-B
的ip:
mysql> stop slave; -- 中止主從同步 mysql> change master to master_host='192.168.190.131', master_port=3306, master_user='backup', master_password='Abc_123456'; -- 配置Master節點的鏈接信息 mysql> start slave; -- 啓動主從同步
一樣配置完成後,使用show slave status\G;
語句查看主從同步狀態,Slave_IO_Running
和Slave_SQL_Running
的值均爲Yes
才能表示主從同步狀態是正常的:
配置好兩個節點的主從同步關係以後,咱們就算是完成了Replication集羣的搭建。接下來咱們在任意一個節點建立一張歸檔表,看看兩個節點之間是否能正常同步數據。具體的建表SQL以下:
create table t_purchase_201909 ( id int unsigned primary key, purchase_price decimal(10, 2) not null comment '進貨價格', purchase_num int unsigned not null comment '進貨數量', purchase_sum decimal(10, 2) not null comment '進貨總價', purchase_buyer int unsigned not null comment '採購者', purchase_date timestamp not null default current_timestamp comment '採購日期', company_id int unsigned not null comment '進貨企業的id', goods_id int unsigned not null comment '商品id', key idx_company_id(company_id), key idx_goods_id(goods_id) ) engine=TokuDB comment '2019年9月的進貨數據歸檔表';
我這裏是可以正常進行同步的,如圖兩個節點都能看到這張表:
到此爲止,咱們就完成了Replication集羣的搭建及測試。接下來就是得讓Replication集羣具備高可用的特性,這就輪到Haproxy上場了。Haproxy是一款提供高可用性、負載均衡以及基於TCP(第四層)和HTTP(第七層)應用的代理軟件。使用Haproxy能夠對MySQL集羣進行負載均衡,賦予集羣高可用性併發揮集羣的性能。
Haproxy因爲是老牌的負載均衡組件了,因此CentOS的yum
倉庫中自帶有該組件的安裝包,安裝起來就很是簡單。安裝命令以下:
[root@HA-01 ~]# yum install -y haproxy
安裝完成後,編輯Haproxy的配置文件,添加監控界面及須要代理的數據庫節點配置:
[root@HA-01 ~]# vim /etc/haproxy/haproxy.cfg # 在文件的末尾添加以下配置項 # 監控界面配置 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 # 負載均衡算法 # roundrobin:輪詢 # static-rr:權重 # leastconn:最少鏈接 # source:請求源ip balance roundrobin # 日誌格式 option tcplog # 須要被負載均衡的主機 server node-A 192.168.190.142:3306 check port 3306 weight 1 maxconn 2000 server node-B 192.168.190.131:3306 check port 3306 weight 1 maxconn 2000 # 使用keepalive檢測死鏈 option tcpka
因爲配置了3306
端口用於TCP
轉發,以及4001
做爲Haproxy監控界面的訪問端口,因此在防火牆上須要開放這兩個端口:
[root@HA-01 ~]# firewall-cmd --zone=public --add-port=3306/tcp --permanent [root@HA-01 ~]# firewall-cmd --zone=public --add-port=4001/tcp --permanent [root@HA-01 ~]# firewall-cmd --reload
完成以上步驟後,啓動Haproxy服務:
[root@HA-01 ~]# systemctl start haproxy
而後使用瀏覽器訪問Haproxy的監控界面,初次訪問會要求輸入用戶名密碼,這裏的用戶名密碼就是配置文件中所配置的:
登陸成功後,就會看到以下頁面:
Haproxy的監控界面提供的監控信息也比較全面,在該界面下,咱們能夠看到每一個主機的鏈接信息及其自身狀態。當主機沒法鏈接時,Status
一欄會顯示DOWN
,而且背景色也會變爲紅色。正常狀態下的值則爲UP
,背景色爲綠色。
另外一個Haproxy節點也是使用以上的步驟進行安裝和配置,這裏就再也不重複了。
Haproxy服務搭建起來後,咱們來使用遠程工具測試一下可否經過Haproxy正常鏈接到數據庫。以下:
鏈接成功後,在Haproxy上執行一些SQL語句,看看可否正常插入數據和查詢數據:
咱們搭建Haproxy是爲了讓Replication集羣具有高可用的,因此最後測試一下Replication集羣是否已具有有高可用性,首先將其中一個節點給停掉:
[root@node-B ~]# systemctl stop mysqld
此時,從Haproxy的監控界面中,能夠看到node-B
這個節點已經處於下線狀態了:
如今集羣中還剩一個節點,而後咱們到Haproxy上執行一些SQL語句,看看是否還能正常插入數據和查詢數據:
從測試結果能夠看到,插入和查詢語句依舊是能正常執行的。也就是說即使此時關掉一個節點整個數據庫集羣還可以正常使用,說明如今Replication集羣是具備高可用性了。
實現了Replication集羣的高可用以後,咱們還得實現Haproxy的高可用,由於Haproxy做爲一個負責接收客戶端請求,並將請求轉發到後端數據庫集羣的入口,不可避免的須要具有高可用性。不然Haproxy出現單點故障,就沒法訪問被Haproxy代理的全部數據庫集羣節點了,這對整個系統的影響是十分巨大的。
在同一時間只須要存在一個可用的Haproxy,不然客戶端就不知道該連哪一個Haproxy了。這也是爲何要採用Keepalived的虛擬IP的緣由,這種機制能讓多個節點互相接替時依舊使用同一個IP,客戶端至始至終只須要鏈接這個虛擬IP。因此實現Haproxy的高可用就要輪到Keepalived出場了,在安裝Keepalived以前須要開啓防火牆的VRRP協議:
[root@HA-01 ~]# firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 0 --protocol vrrp -j ACCEPT [root@HA-01 ~]# firewall-cmd --reload
而後就可使用yum
命令安裝Keepalived了:
[root@HA-01 ~]# yum install -y keepalived
安裝完成後,編輯keepalived的配置文件:
[root@HA-01 ~]# mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak # 不使用自帶的配置文件 [root@HA-01 ~]# vim /etc/keepalived/keepalived.conf vrrp_instance VI_1 { state MASTER interface ens32 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.190.101 } }
配置說明:
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服務:
[root@HA-01 ~]# systemctl start keepalived
當keepalived服務啓動成功,使用ip addr
命令能夠查看到網卡綁定的虛擬IP:
另外一個節點也是使用以上的步驟進行安裝和配置,這裏就再也不重複了。不過要注意virtual_router_id
不能配置成同樣的,而virtual_ipaddress
則必須配置成同一個虛擬ip。
以上咱們完成了Keepalived的安裝與配置,最後咱們來測試Keepalived服務是否正常可用,以及測試Haproxy是否已具備高可用性。
首先,在其餘節點上測試虛擬IP可否正常ping
通,若是不能ping
通就須要檢查配置了。如圖,我這裏是能正常ping
通的:
常見的虛擬IP ping不通的狀況:
確認可以從外部ping
通Keepalived的虛擬IP後,使用Navicat測試可否經過虛擬IP鏈接到數據庫:
鏈接成功後,執行一些語句測試可否正常插入、查詢數據:
到此就基本沒什麼問題了,最後測試一下Haproxy的高可用性,將其中一個Haproxy節點上的Keepalived和Haproxy服務給關掉:
[root@HA-01 ~]# systemctl stop keepalived [root@HA-01 ~]# systemctl stop haproxy
而後再次執行執行一些語句測試可否正常插入、查詢數據,以下能正常執行表明Haproxy節點已具備高可用性:
最後將全部的服務恢復成運行狀態,驗證中止的節點恢復以後數據是不是一致的。以下,我這裏兩個Replication節點的數據都是一致的:
到此爲止,咱們就完成了高可用Replication集羣的搭建。接下來就是實踐如何將大量的冷數據從PXC集羣分片中剝離出來並歸檔到Replication集羣中,我這裏有兩個PXC集羣分片:
每一個分片裏都有一張t_purchase
表,其建表SQL以下。
create table t_purchase ( id int unsigned primary key, purchase_price decimal(10, 2) not null comment '進貨價格', purchase_num int unsigned not null comment '進貨數量', purchase_sum decimal(10, 2) not null comment '進貨總價', purchase_buyer int unsigned not null comment '採購者', purchase_date timestamp not null default current_timestamp comment '採購日期', company_id int unsigned not null comment '進貨企業的id', goods_id int unsigned not null comment '商品id', key idx_company_id(company_id), key idx_goods_id(goods_id) ) comment '進貨表';
每一個分片合計共存儲了100w條進貨數據:
其中有60w條進貨數據的採購日期都是2019-11-01
以前的:
如今的需求是將2019-11-01
以前的數據都剝離出來進行歸檔,這要如何實現呢?本身寫代碼確定是比較麻煩的,好在Percona工具包裏提供了一個用於歸檔數據的工具:pt-archiver
,使用該工具能夠很輕鬆的完成數據歸檔,免除了本身寫歸檔程序的麻煩。pt-archiver
主要有兩個用途:
想要使用pt-archiver
首先得安裝Percona工具包:
[root@node-A ~]# yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm [root@node-A ~]# percona-release enable ps-80 release [root@node-A ~]# yum install -y percona-toolkit
安裝完成後,驗證pt-archiver
命令是否可用:
[root@node-A ~]# pt-archiver --version pt-archiver 3.1.0 [root@node-A ~]#
接着就可使用pt-archiver
命令進行數據的歸檔了,首先須要在Replication集羣中建立一張歸檔表,表名以歸檔的數據日期爲後綴,存儲引擎使用TokuDB。具體的建表SQL以下:
create table t_purchase_201910 ( id int unsigned primary key, purchase_price decimal(10, 2) not null comment '進貨價格', purchase_num int unsigned not null comment '進貨數量', purchase_sum decimal(10, 2) not null comment '進貨總價', purchase_buyer int unsigned not null comment '採購者', purchase_date timestamp not null default current_timestamp comment '採購日期', company_id int unsigned not null comment '進貨企業的id', goods_id int unsigned not null comment '商品id', key idx_company_id(company_id), key idx_goods_id(goods_id) ) engine=TokuDB comment '2019年10月的進貨數據歸檔表';
而後使用pt-archiver
命令完成數據歸檔,以下示例:
[root@node-A ~]# pt-archiver --source h=192.168.190.100,P=3306,u=admin,p=Abc_123456,D=test,t=t_purchase --dest h=192.168.190.101,P=3306,u=archive,p=Abc_123456,D=test,t=t_purchase_201910 --no-check-charset --where 'purchase_date < "2019-11-01 0:0:0"' --progress 50000 --bulk-delete --bulk-insert --limit=100000 --statistics
pt-archiver
命令是使用load data
語句進行數據導入的,因此要確保MySQL開啓了local_infile
。若是沒有開啓的話歸檔數據會失敗,可使用set global local_infile = 'ON';
語句來開啓local_infile
。命令參數說明:
--source
:指定從哪一個數據庫讀取數據--dest
:指定將數據歸檔至哪一個數據庫--no-check-charset
:不檢查數據的字符集--where
:指定將哪些數據進行歸檔,在本例中就是將2019-09-11
以前的數據進行歸檔--progress
:指定當歸檔完多少條數據時打印一次狀態信息--bulk-delete
:指定批量刪除歸檔數據。數據的刪除有事務保證,不會出現未歸檔成功就將數據刪除了的狀況--bulk-insert
:指定批量寫入歸檔數據--limit
:指定每次歸檔多少條數據--statistics
:歸檔數據完成後打印統計信息等待大約15分鐘左右數據就歸檔完成了,輸出的統計信息以下:
此時在Replication集羣上能夠看到那60w數據都已經存儲到了歸檔表中:
而本來的PXC集羣中就只剩40w數據了:
如此一來咱們就完成了冷熱數據分離,並將大量的冷數據存儲至指定的歸檔數據庫中。
pt-archiver
能夠導出大量數據並歸檔存儲,且簡便易行