【重磅】微信開源PhxSQL:高可用、強一致的MySQL集羣


開源地址:

https://github.com/tencent-wechat/phxsql

點擊閱讀原文可自動跳轉到github地址


PhxSQL是一個兼容MySQL、服務高可用、數據強一致的關係型數據庫集羣。PhxSQL以單Master多Slave方式部署,在集羣內超過一半機器存活的情況下,可自身實現自動Master切換,且保證數據一致性。


PhxSQL基於Percona 5.6開發。Percona是MySQL的一個分支,功能和實現與MySQL基本一致。因此本文後續直接把MySQL作爲討論對象。


MySQL半同步複製存在缺陷,在Master進行切換的場景下,數據難以保證一致。

  • 當舊Master複製失敗時,舊Master和Updated Slave(已收到Binlog的Slave)需要回滾數據。

  • 當Master進行切換時,舊Master仍有部分Client進行讀寫。

 

關於MySQL半同步複製的數據一致性問題可查看微信後臺團隊公衆號文章MySQL半同步複製的數據一致性探討

 

PhxSQL的設計是爲了解決MySQL半同步複製的不足,使MySQL集羣在Master切換過程中保證數據的一致。


PhxSQL架構


     

圖1 PhxSQL 三層架構

 

爲了解決MySQL的兩個問題(Binlog複製和Master切換),PhxSQL設計了兩個模塊(Phxbinlogsvr、Phxsqlproxy)和一個MySQL插件(Phxsync)。Phxbinlogsvr負責處理MySQL的Binlog複製和Master管理;Phxsqlproxy負責透傳Client請求到Master;Phxsync插件負責MySQL和Phxbinlogsvr的交互。 一臺部署了Phxsqlproxy,MySQL和Phxbinlogsvr的機器稱爲PhxSQL Node。如圖1。

 

PhxSQL複製流程




圖2.1 MySQL複製流程



圖2.2 PhxSQL複製流程

 

圖2 MySQL和PhxSQL的數據複製流程

 

在PhxSQL中,Phxbinlogsvr負責管理MySQL的角色和存儲MySQL的Binlog,Phxbinlogsvr和其管理的MySQL部署在同一臺物理機上。

 

MySQL Master在Send Event階段不再把Binlog複製給Slave,而是通過Phxsync插件,把數據複製到Phxbinlogsvr集羣。

 

MySQL Slave也不再從Master獲取Binlog,而是從本機的Phxbinlogsvr獲取。

 

Phxbinlogsvr集羣使用Paxos協議進行數據複製。


PhxSQL使用PhxPaxos庫,詳情請查看微信後臺團隊公衆號文章微信自研生產級paxos類庫PhxPaxos實現原理介紹



圖3 Phxbinlogsvr形成一個可靠日誌存儲



圖4 重啓向Phxbinlogsvr詢問PendingBinlog狀態

 

從邏輯上來看,利用Paxos協議進行復制,使Phxbinlogsvr形成一個可靠的日誌存儲。PhxSQL可以看成是爲MySQL增加了一個用Paxos實現的可靠Binlog存儲,只要集羣中多數派機器存活,就可以解決半同步複製的回滾問題。如圖3。


分別從Master和Slave的角度來解釋:

  1. Master重啓時,通過詢問Phxbinlogsvr(多數派)Pending Binlog是否存在來決定是否需要回滾。如圖4。

  2. Slave從本機Phxbinlogsvr能拉取到的Binlog都已經經過Paxos協議成功複製到多數派機器,因此對於Slave來說不存在回滾的問題。

 

Phxbinlogsvr通過Paxos協議複製數據,很好的解決了MySQL中需要手動回滾Binlog和在大集羣時同時需要回滾Updated Slave上的Binlog的問題。

 

PhxSQL的Master管理




圖5 多個Master同時寫入數據,導致數據不一致


MySQL多Master同時寫入會導致數據的不一致。如圖5,機器A是舊Master,在收到機器B成爲了新Master的消息之前提交了Transaction 3;而同時機器B已成爲新Master,Transaction 3則會留在機器A而未複製到機器B,最終兩機的數據不一致。

 

MySQL多Master問題的產生,源於機器間無法得知當前Master的狀態,最後導致兩臺機器的數據不一致。


即使使用外部服務(例如zookeeper)也無法解根本問題。

  1. 對Master查詢和查詢之後的操作不是原子操作,無法保證操作時的準確狀態(例如機器A向外部服務查詢得知自己是Master,然後執行復制Binlog操作。但期間出現故障導致兩個操作之間停頓了很長時間(譬如1天)。在該期間內Master被切換,使得機器A在執行復制Binlog時,已不再是Master,導致了多Master的情況發生。)

  2. Master管理依賴外部服務的穩定性。


多Master問題由於細節太多,暫不在此討論。

 

PhxSQL自身進行了Master管理,具有以下特點:

  1. Master通過Paxos協議投票選出。

  2. Master帶有租約,並定時續租。租約過期後,需重新選舉新的Master。

  3. 全局只有1個Master,或者沒有Master存在。

  4. 有效拒絕過期Master的非法寫入。

 

PhxSQL的Master自動切換



PhxSQL實現了舊Master的自動數據回滾和Master管理,使得PhxSQL可以安全地實現Master的自動切換,提供高可用服務。和常見的MySQL切換Master方案不同,PhxSQL在切換Master之後仍然保證集羣內各機數據一致。



圖6

PhxSQL自動Master流程如下:

  1. Slave機器上的Phxbinlogsvr定期檢查Master是否過期。如果過期轉第2步,否則繼續第1步;

  2. Phxbinlogsvr檢查本機MySQL是否已執行完所有Binlog。如果已完成轉第3步,否則繼續第1步;

  3. Phxbinlogsvr發起投票選舉新的Master。如果投票成功,提升本機MySQL爲Master,關閉readonly開關;否則繼續第1步;

  4. 舊Master恢復,本機的Phxbinlogsvr查詢發現已不是Master,切換MySQL角色爲Slave,設置從本機Phxbinlogsvr拉取Binlog,並開啓readonly開關。

 

Phxsqlproxy請求透傳



Phxbinlogsvr解決了多Master同時寫入的問題,使得MySQLClient向舊Master寫入數據會產生失敗。雖然保證了數據的一致性,但仍存在下面2個問題:

  1. MySQLClient持續向舊Master寫入數據,從而持續的失敗。(服務不可用)

  2. 部分MySQLClient向新Master寫入數據,但其他MySQLClient仍然向舊Master讀取數據,導致讀不到最新的數據。



圖7

 

上述兩個問題都是由於MySQLClient的Master信息更新不及時;部分Client沒有及時更新,使得有可能產生PhantomRead(兩次讀的結果不一致)。



圖8 Phxsqlproxy的請求透傳

 

若Slave機器被訪問,Phxsqlproxy則會把請求透傳到Master機器的Phxsqlproxy。由於PhxSQL Master的全局唯一性,保證了只存在一臺MySQL被訪問。從而解決了多臺機器同時被讀寫的問題。


PhxSQL性能



使用sysbench工具對PhxSQL和MySQL的半同步複製進行了性能對比。PhxSQL因爲增加了Phxsqlproxy,導致讀性能比原生MySQL略低;但由於PhxPaxos的實現比MySQL的半同步更加高效,讓PhxSQL的寫性能比半同步複製更好。

 

PhxSQL比MySQL讀性能比原生MySQL略低,但寫性能比MySQL半同步複製更好。


讀性能
寫性能
Client線程數QPS耗時QPS耗時
200約降低3%耗時約增加2%約增高25%約降低20%
500約降低13%約增加10%約增高16%約降低10%



測試環境和結果如下: 

機型信息

CPU : Intel(R) Xeon(R) CPU E5-2420 0 @ 1.90GHz * 24

內存 : 32G

磁盤 : SSD Raid10

網絡互Ping耗時

Master -> Slave : 3 ~ 4ms

Client -> Master : 4ms

壓測工具和參數

sysbench –oltp-tables-count=10 –oltp-table-size=1000000 –num-threads=500 –max-requests=100000 –report-interval=1 –max-time=200

壓測內容

PhxSQL和半同步複製在Client線程200和500的環境下進行下面方式的壓測:

  • insert.lua (100%寫)

  • select.lua (0%寫)

  • OLTP.lua (20%寫)


壓測結果

Client線程數:200


insert.lua (100%寫)

QPS耗時

PhxSQL

507639.34/56.93

MySQL

半同步

405549.27/66.64


select.lua (0%寫)

QPS耗時

PhxSQL

463344.21/5.12

MySQL

半同步

475284.10/5.00


OLTP.lua (20%寫)

QPS耗時

PhxSQL

25657140.16/186.39

MySQL

半同步

20391176.39/226.76


Client線程數:500


insert.lua (100%寫)

QPS耗時

PhxSQL

826060.41/83.14

MySQL

半同步

707270.60/91.72


select.lua (0%寫)

QPS耗時

PhxSQL

1059284.58/5.81

MySQL

半同步

1215354.17/5.08



OLTP.lua (20%寫)

QPS耗時

PhxSQL

46543192.93/242.85

MySQL

半同步

33229270.38/345.84

注:耗時分別爲測試結果的平均耗時/95%分位數耗時,單位ms


總結


      

PhxSQL解決了MySQL半同步複製中數據回滾和多Master的問題,使其能實現自動Master切換且保證數據一致。PhxSQL因爲增加了Phxsqlproxy,導致讀性能比原生MySQL略低;由於PhxPaxos的實現比MySQL的半同步更加高效,讓PhxSQL的寫性能比半同步複製更好。




開源地址:

https://github.com/tencent-wechat/phxsql

點擊閱讀原文可自動跳轉到github地址


附錄:

微信自研生產級paxos類庫PhxPaxos實現原理介紹

微信開源C/C++ RPC框架PhxRPC

MySQL半同步複製的數據一致性探討


原文:
http://mp.weixin.qq.com/s?__biz=MzI4NDMyNTU2Mw==&mid=2247483783&idx=1&sn=a2d6e589f1f591ded7703eb74aefccbe&scene=0#wechat_redirect

發佈了84 篇原創文章 · 獲贊 135 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章