- PXC集群的概述及搭建
- PXC原理描述
- 在Centos部署基於Mysql高可用方案操作過程
- [root@percona1 ~]# cat /etc/my.cnf
- Path to Galera library
- Cluster connection URL contains the IPs of node#1, node#2 and node#3
- In order for Galera to work correctly binlog format should be ROW
- MyISAM storage engine has only experimental support
- This changes how InnoDB autoincrement locks are managed and is a requirement for Galera
- Node #1 address
- SST method
- Cluster name
- Authentication for SST method
- 配置文件各項配置意義
- 啟動數據庫(三個節點都要操作):
- 此參數查看是否開啟
- 查看集群的成員數
- 這個查看wsrep的相關參數
- [root@percona1 ~]# cat /etc/my.cnf
PXC集群的概述及搭建
PXC集群的簡介
Percona XtraDB Cluster(下文簡稱PXC集群)提供了MySQL高可用的一種實現方法。PXC集群以節點組成(推薦至少3節點,便於故障恢復,后面會討論兩節點的情況),每個節點都是基於常規的 MySQL/Percona Server,意味着你可以從集群中分離出某節點單獨使用。集群中每個節點都包含完整的數據。
PXC集群主要由兩部分組成:
Percona Server with XtraDB和Write Set Replication patches(使用了Galera library,一個通用的用於事務型應用的同步、多主復制插件)。
PXC的特性和優點:
1、同步復制
2、支持多主復制
3、支持並行復制
4、作為高可用方案,相比其他方案其結構和實施相對簡單明了
PXC的局限和劣勢:
1) 版本(5.6.20)的復制只支持InnoDB引擎,其他存儲引擎的更改不復制。然而,DDL(Data Definition Language) 語句在statement級別被復制,並且,對mysql.*表的更改會基於此被復制。例如CREATE USER...語句會被復制,但是 INSERT INTO mysql.user...語句則不會。(也可以通過wsrep_replicate_myisam參數開啟myisam引擎的 復制,但這是一個實驗性的參數)。
2)由於PXC集群內部一致性控制的機制,事務有可能被終止,原因如下:集群允許在兩個節點上通知執行操作同一行的兩個事務,但是只有一個能執行成功,另一個 會被終止,同時集群會給被終止的客戶端返回死鎖錯誤(Error: 1213 SQLSTATE: 40001 (ER_LOCK_DEADLOCK)).
3)寫入效率取決於節點中最弱的一台,因為PXC集群采用的是強一致性原則,一個更改操作在所有節點都成功才算執行成功
4)所有表都要有主鍵;
5)不支持LOCK TABLE等顯式鎖操作;
6)鎖沖突、死鎖問題相對更多;
7)不支持XA;
8)集群吞吐量/性能取決於短板;
9)新加入節點采用SST時代價高;
10)存在寫擴大問題;
11)如果並發事務量很大的話,建議采用InfiniBand網絡,降低網絡延遲;
事實上,采用PXC的主要目的是解決數據的一致性問題,高可用是順帶實現的。因為PXC存在寫擴大以及短板效應,並發效率會有較大損失,類似semi sync replication機制。
PXC原理描述
分布式系統的CAP理論:
C:一致性,所有的節點數據一致
A:可用性,一個或者多個節點失效,不影響服務請求
P:分區容忍性,節點間的連接失效,仍然可以處理請求
其實,任何一個分布式系統,需要滿足這三個中的兩個。
PXC會使用大概是4個端口號
3306:數據庫對外服務的端口號
4444:請求SST SST: 指數據一個鏡象傳輸 xtrabackup , rsync ,mysqldump
4567: 組成員之間進行溝通的一個端口號
4568: 傳輸IST用的。相對於SST來說的一個增量。
一些名詞介紹:
WS:write set 寫數據集
IST: Incremental State Transfer 增量同步
SST:State Snapshot Transfer 全量同步
PXC環境所涉及的端口:
mysql實例端口
10Regular MySQL port, default 3306.
#pxc cluster相互通訊的端口
2)Port for group communication, default 4567. It can be changed by the option:
wsrep_provider_options ="gmcast.listen_addr=tcp://0.0.0.0:4010; "
#用於SST傳送的端口
3)Port for State Transfer, default 4444. It can be changed by the option:
wsrep_sst_receive_address=10.11.12.205:5555
#用於IST傳送的端口
4)Port for Incremental State Transfer, default port for group communication + 1 (4568). It can be changed by the option:
wsrep_provider_options = "ist.recv_addr=10.11.12.206:7777; "
PXC的架構示意圖
數據讀寫示意圖
下面看傳統復制流程
異步復制
半同步復制,超過10秒的閥值會退化為異步
PXC原理圖
從上圖可以看出:
當client端執行dml操作時,將操作發給server,server的native進程處理請求,client端執行commit,server將復制寫數據集發給group(cluster),cluster
中每個動作對應一個GTID,其它server接收到並通過驗證(合並數據)后,執行appyl_cb動作和commit_cb動作,若驗證沒通過,則會退出處理;當前server節點驗證通
過后,執行commit_cb,並返回,若沒通過,執行rollback_cb。
只要當前節點執行了commit_cb和其它節點驗證通過后就可返回。
3306:數據庫對外服務的端口號
4444:請求SST,在新節點加入時起作用
4567:組成員之間溝通的端口
4568:傳輸IST,節點下線,重啟加入時起作用
SST:全量同步
IST:增量同步
問題:如果主節點寫入過大,apply_cb時間跟不上,怎么處理?
Wsrep_slave_threads參數配置成cpu的個數相等或是1.5倍。
用戶發起Commit,在收到Ok之前,集群每次發起一個動作,都會有一個唯一的編號 ,也就是PXC獨有的Global Trx Id。
動作發起者是commit_cb,其它節點多了一個動作: apply_cb
上面的這些動作,是通過那個端號交互的?
4567,4568端口,IST只是在節點下線,重啟加入那一個時間有用
4444端口,只會在新節點加入進來時起作用
PXC結構里面,如果主節點寫入過大,apply_cb 時間會不會跟不上,那么wsrep_slave_threads參數 解決apply_cb跟不上問題 配置成和CPU的個數相等或是1.5倍
當前節點commit_cb 后就可以返回了,推過去之后,驗證通過就行了可以返回客戶端了,cb也就是commit block 提交數據塊.
PXC啟動和關閉過程
State Snapshot Transfer(SST),每個節點都有一份獨立的數據,當用mysql bootstrap-pxc啟動第一個節點,在第一個節點上把帳號初始化,其它節點啟動后加入進來。集群中有哪些節點是由wsrep_cluster_address = gcomm://xxxx,,xxxx,xxx參數決定。第一個節點把自己備份一下(snapshot)傳給加入的新節點,第三個節點的死活是由前兩個節點投票決定。
狀態機變化階段:
1)OPEN: 節點啟動成功,嘗試連接到集群,如果失敗則根據配置退出或創建新的集群
2)PRIMARY: 節點處於集群PC中,嘗試從集群中選取donor進行數據同步
3)JOINER: 節點處於等待接收/接收數據文件狀態,數據傳輸完成后在本地加載數據
4)JOINED: 節點完成數據同步工作,嘗試保持和集群進度一致
5)SYNCED:節點正常提供服務:數據的讀寫,集群數據的同步,新加入節點的sst請求
6)DONOR(貢獻數據者):節點處於為新節點准備或傳輸集群全量數據狀態,對客戶端不可用。
狀態機變化因素:
1)新節點加入集群
2)節點故障恢復
3)節點同步失效
傳輸SST有幾種方法:
1)mysqldump
2)xtrabackup
3)rsync
比如有三個節點:node1、node2、node3
當node3停機重啟后,通過IST來同步增量數據,來完成保證與node1和node2的數據一致,IST的實現是由wsrep_provider_options="gcache.size=1G"參數決定,
一般設置為1G大,參數大小是由什么決定的,根據停機時間,若停機一小時,需要確認1小時內產生多大的binlog來算出參數大小。
假設這三個節點都關閉了,會發生什么呢?
全部傳SST,因為gcache數據沒了
全部關閉需要采用滾動關閉方式:
1)關閉node1,修復完后,啟動加回來;
2)關閉node2,修復完后,啟動加回來;
3)......,直到最后一個節點
4)原則要保持Group里最少一個成員活着
數據庫關閉之后,最會保存一個last Txid,所以啟動時,先要啟動最后一個關閉的節點,啟動順序和關閉順序剛好相反。
wsrep_recover=on參數在啟動時加入,用於從log中分析gtid。
怎樣避免關閉和啟動時數據丟失?
1)所有的節點中最少有一個在線,進行滾動重啟;
2)利用主從的概念,把一個從節點轉化成PXC里的節點
PXC要注意的問題
1)腦裂:任何命令執行出現unkown command ,表示出現腦裂,集群兩節點間4567端口連不通,無法提供對外服務。
SET GLOBAL wsrep_provider_options="pc.ignore_sb=true";
2)並發寫:三個節點的自增起始值為1、2、3,步長都為3,解決了insert問題,但update同時對一行操作就會有問題,出現:
Error: 1213 SQLSTATE: 40001,所以更新和寫入在一個節點上操作。
3)DDL:引起全局鎖,采用:pt-online-schema-change
4)MyISAM引擎不能被復制,只支持innodb
5)pxc結構里面必須有主鍵,如果沒有主建,有可能會造成集中每個節點的Data page里的數據不一樣
6)不支持表級鎖,不支持lock /unlock tables
7)pxc里只能把slow log ,query log 放到File里
8)不支持XA事務
9)性能由集群中性能最差的節點決定
特別說明
在實際使用時,我們知道服務的部署時根據需要后來增加的,所以相信在需要用到PXC做高可用時,已經在服務器上安裝了Mysql,並跑了業務。這時候我們會發現存在錯誤,大致如下
大致意思時PID問題。其實percona自身就是mysql,你要原來的mysql干嘛,所以這時候應該殺死原來的Mysql,可能你又要問了那原來跑在Mysql的服務怎么辦?備份還原就可以了。特此說明,以供道友參考,本人在此就出現了很大的困惑,最后才相通問題的解決方案,所以特別加冰了。
在Centos部署基於Mysql高可用方案操作過程
官方配置說明:
https://www.percona.com/doc/percona-xtradb-cluster/5.5/howtos/centos_howto.html
環境描述
[root@db02 ~]# uname -r
2.6.32-696.el6.x86_64
[root@db02 ~]# uname -m
x86_64
[root@db02 ~]# cat /etc/redhat-release
CentOS release 6.10 (Final)
db02 | 10.0.0.52 | percona1 |
---|---|---|
db05 | 10.0.0.55 | percona2 |
db08 | 10.0.0.58 | percona3 |
三個節點上的iptables最好關閉(否則就要開放3306、4444、4567、4568端口的訪問)、關閉selinux
三個節點都要執行以下操作
yum -y groupinstall Base Compatibility libraries Debugging Tools Dial-up Networking suppport Hardware monitoring utilities Performance Tools Development tools
yum install http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm -y
yum install Percona-XtraDB-Cluster-55 -y
注:可以選擇源碼或者yum,在此使用yum安裝。
數據庫配置
選擇一個node作為名義上的master,下面就以db02為master,只需要修改mysql的配置文件--/etc/my.cnf
[root@percona1 ~]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql
user=mysql
Path to Galera library
wsrep_provider=/usr/lib64/libgalera_smm.so
Cluster connection URL contains the IPs of node#1, node#2 and node#3
wsrep_cluster_address=gcomm://10.0.0.52,10.0.0.55,10.0.0.56
In order for Galera to work correctly binlog format should be ROW
binlog_format=ROW
MyISAM storage engine has only experimental support
default_storage_engine=InnoDB
This changes how InnoDB autoincrement locks are managed and is a requirement for Galera
innodb_autoinc_lock_mode=2
Node #1 address
wsrep_node_address=10.0.0.52
SST method
wsrep_sst_method=xtrabackup-v2
Cluster name
wsrep_cluster_name=my_centos_cluster
Authentication for SST method
wsrep_sst_auth="sstuser:s3cret"
配置文件各項配置意義
wsrep_provider:指定Galera庫的路徑
wsrep_cluster_name:Galera集群的名稱
wsrep_cluster_address:Galera集群中各節點地址。地址使用組通信協議gcomm://(group communication)
wsrep_node_name:本節點在Galera集群中的名稱
wsrep_node_address:本節點在Galera集群中的通信地址
wsrep_sst_method:state_snapshot_transfer(SST)使用的傳輸方法,可用方法有mysqldump、rsync和xtrabackup,前兩者在傳輸時都需要對Donor加全局只讀鎖(FLUSH TABLES WITH READ LOCK),xtrabackup則不需要(它使用percona自己提供的backup lock)。強烈建議采用xtrabackup
wsrep_sst_auth:在SST傳輸時需要用到的認證憑據,格式為:"用戶:密碼"
pxc_strict_mode:是否限制PXC啟用正在試用階段的功能,ENFORCING是默認值,表示不啟用
binlog_format:二進制日志的格式。Galera只支持row格式的二進制日志
default_storage_engine:指定默認存儲引擎。Galera的復制功能只支持InnoDB
innodb_autoinc_lock_mode:只能設置為2,設置為0或1時會無法正確處理死鎖問題
啟動數據庫(三個節點都要操作):
db02的啟動方式:
etc/init.d/mysql bootstrap-pxc
.....................................................................
如果是centos7,則啟動命令如下:
systemctl start mysql@bootstrap.service
.....................................................................
若是重啟的話,就先kill,然后刪除pid文件后再執行上面的啟動命令。
配置數據庫(三個節點都要操作)
mysql> show status like 'wsrep%';
+----------------------------+--------------------------------------+
| Variable_name | Value |
+----------------------------+--------------------------------------+
| wsrep_local_state_uuid | a7f5cbaf-a48b-11e8-b84f-a2501fa64600 |
| wsrep_protocol_version | 4 |
| wsrep_last_committed | 0 |
| wsrep_replicated | 0 |
| wsrep_replicated_bytes | 0 |
| wsrep_received | 2 |
| wsrep_received_bytes | 129 |
| wsrep_local_commits | 0 |
| wsrep_local_cert_failures | 0 |
| wsrep_local_replays | 0 |
| wsrep_local_send_queue | 0 |
| wsrep_local_send_queue_avg | 0.000000 |
| wsrep_local_recv_queue | 0 |
| wsrep_local_recv_queue_avg | 0.000000 |
| wsrep_flow_control_paused | 0.000000 |
| wsrep_flow_control_sent | 0 |
| wsrep_flow_control_recv | 0 |
| wsrep_cert_deps_distance | 0.000000 |
| wsrep_apply_oooe | 0.000000 |
| wsrep_apply_oool | 0.000000 |
| wsrep_apply_window | 0.000000 |
| wsrep_commit_oooe | 0.000000 |
| wsrep_commit_oool | 0.000000 |
| wsrep_commit_window | 0.000000 |
| wsrep_local_state | 4 |
| wsrep_local_state_comment | Synced |
| wsrep_cert_index_size | 0 |
| wsrep_causal_reads | 0 |
| wsrep_incoming_addresses | 10.0.0.52:3306 |
| wsrep_cluster_conf_id | 1 |
| wsrep_cluster_size | 1 |
| wsrep_cluster_state_uuid | a7f5cbaf-a48b-11e8-b84f-a2501fa64600 |
| wsrep_cluster_status | Primary |
| wsrep_connected | ON |
| wsrep_local_bf_aborts | 0 |
| wsrep_local_index | 0 |
| wsrep_provider_name | Galera |
| wsrep_provider_vendor | Codership Oy info@codership.com |
| wsrep_provider_version | 2.12(r318911d) |
| wsrep_ready | ON |
| wsrep_thread_count | 2 |
+----------------------------+--------------------------------------+
數據庫用戶名密碼的設置
mysql> UPDATE mysql.user SET password=PASSWORD("Passw0rd") where user='root';
創建、授權、同步賬號
mysql> CREATE USER 'sstuser'@'localhost' IDENTIFIED BY 's3cret';
mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON . TO 'sstuser'@'localhost';
mysql> FLUSH PRIVILEGES;
................注意下面幾個察看命令...............
mysql> SHOW VARIABLES LIKE 'wsrep_cluster_address';
如果配置了指向集群地址,上面那個參數值,應該是你指定集群的IP地址
此參數查看是否開啟
mysql> show status like 'wsrep_ready';
查看集群的成員數
mysql> show status like 'wsrep_cluster_size';
這個查看wsrep的相關參數
mysql> show status like 'wsrep%';
4)那么db05和db08只需要配置my.cnf文件中的wsrep_node_address這個參數,將其修改為自己的ip地址即可。
注:
在此因為篇幅原因不在給出db05,db08的配置,如有需要請評論說出,本人會及時回復
node2和node3的啟動方式:
[root@percona2 ~]# /etc/init.d/mysql start
注意事項
-> 除了名義上的master之外,其它的node節點只需要啟動mysql即可。
-> 節點的數據庫的登陸和master節點的用戶名密碼一致,自動同步。所以其它的節點數據庫用戶名密碼無須重新設置。
也就是說,如上設置,只需要在名義上的master節點(如上的node1)上設置權限,其它的節點配置好/etc/my.cnf后,只需要啟動mysql就行,權限會自動同步過來。
如上的node2,node3節點,登陸mysql的權限是和node1一樣的(即是用node1設置的權限登陸)
如果上面的node2、node3啟動mysql失敗,比如/var/lib/mysql下的err日志報錯如下:
[ERROR]WSREP: gcs/src/gcs_group.cpp:long int gcs_group_handle_join_msg(gcs_
解決辦法:
-> 查看節點上的iptables防火牆是否關閉;檢查到名義上的master節點上的4567端口是否連通(telnet)
-> selinux是否關閉
-> 刪除名義上的master節點上的grastate.dat后,重啟名義上的master節點的數據庫;當然當前節點上的grastate.dat也刪除並重啟數據庫
測試
在任意一個node上,進行添加,刪除,修改操作,都會同步到其他的服務器,是現在主主的模式,當然前提是表引擎必須是innodb,因為galera目前只支持innodb的表。
mysql> show status like 'wsrep%';
在db08上創建一個庫
create database zisefeizhu;
然在在db02和db05上查看,會發現自動同步過來
show databases;
在db02上的zisefeizhu庫下創建表,插入數據
mysql> use zisefeizhu;
Database changed
mysql> create table test(
-> id int(5));
Query OK, 0 rows affected (0.11 sec)
mysql> insert into test values(1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into test values(2);
Query OK, 1 row affected (0.02 sec)
同樣,在其它的節點上查看,也是能自動同步過來
mysql> select * from zisefeizhu.test;
新增節點加入Galera集群
1.新節點加入Galera集群
新節點加入集群時,需要從當前集群中選擇一個Donor節點來同步數據,也就是所謂的state_snapshot_tranfer(SST)過程。SST同步數據的方式由選項wsrep_sst_method決定,一般選擇的是xtrabackup。
必須注意,新節點加入Galera時,會刪除新節點上所有已有數據,再通過xtrabackup(假設使用的是該方式)從Donor處完整備份所有數據進行恢復。所以,如果數據量很大,新節點加入過程會很慢。而且,在一個新節點成為Synced狀態之前,不要同時加入其它新節點,否則很容易將集群壓垮。
如果是這種情況,可以考慮使用wsrep_sst_method=rsync來做增量同步,既然是增量同步,最好保證新節點上已經有一部分數據基礎,否則和全量同步沒什么區別,且這樣會對Donor節點加上全局read only鎖。
2.舊節點加入Galera集群
如果舊節點加入Galera集群,說明這個節點在之前已經在Galera集群中呆過,有一部分數據基礎,缺少的只是它離開集群時的數據。這時加入集群時,會采用IST(incremental snapshot transfer)傳輸機制,即使用增量傳輸。
但注意,這部分增量傳輸的數據源是Donor上緩存在GCache文件中的,這個文件有大小限制,如果缺失的數據范圍超過已緩存的內容,則自動轉為SST傳輸。如果舊節點上的數據和Donor上的數據不匹配(例如這個節點離組后人為修改了一點數據),則自動轉為SST傳輸。
關於GCache以及Galera是如何判斷數據狀態的,本文不展開描述,可參見https://severalnines.com/blog/understanding-gcache-galera