從mysql主從複製到微信開源的phxsql

嚴格的來講,微信開源的phxsql不是數據庫,而是一個數據庫的插件;前端

傳統的互聯網數據庫結構通常是這樣的:mysql

 

服務訪問數據庫是經過分片來的:算法

 

除了這種基於hash的分片,還有一種基於range的分片方式sql

一般,基於range的分片場景下會引入一個新的服務來保存range分片的元信息,列如etcd:數據庫

數據庫鏈接是這樣進行的:後端

    第1步, 先監控etcd服務上的range信息變化;微信

    第2步, 讀取etcd服務上的range信息;插件

    第3步, 接收到sql請求,解析sql語句,根據分片信息決定鏈接哪一個數據庫進行操做;日誌

著名的開源數據庫TiDB就是range來作數據庫的水平拆分;blog

基於hash的數據庫分片如今已經不多用了,由於擴容時很是麻煩;你能夠自行腦補一下,1000臺數據庫的記錄擴展到1500臺,在不中斷業務的狀況下的操做;

上面的內容有點跑題,咱們接下來看看主從複製:

爲了防止某個庫掛掉以後,記錄丟失,有了主從複製

固然,主從複製還能夠知足讀寫分離,減低主庫的負擔

數據庫鏈接的邏輯:

    第1步, 解析sql;

    第2步, 判斷sql是讀(insert, update, delete)仍是寫(select);

    第3步, 落到相應的庫上;

因爲從庫獲取主庫的記錄有延時,因此讀可能會失敗,好比你剛發佈了個帖子,卻不能立刻查到;

或者還有更壞的狀況,你剛發了個帖子,主庫掛了,這條記錄還沒同步到從庫;這樣帖子就丟了;

若是隻是丟了帖子,狀況還不算糟,從新發個帖子就是了;若是是在金融場景下,問題可能就麻煩了,好比下面的場景:

 mysql主從複製可能會致使數據不一致,這是問題1;

再看下面的場景,若是數據庫鏈接是基於故障自動切換的,則有可能會產生主庫和從庫同時被寫的問題;

這種場景下,主從庫的數據也會不一致,這是第二個問題;

爲了解決第一個問題,phxsql引入了第一個插件BinLogSvr:

phxsql增長了一個進程BinLogSvr,用來管理mysql日誌;

主庫的邏輯變成了這樣:

    第1步, 收到sql請求;

    第2步, 準備sql執行;

    第3步, 寫入BinLogSvr;

        BinLogSvr用paxos協議,將這條日誌複製到mysql集羣中的其餘機器上;

        BinLogSvr返回成功;

    第4步, Commit數據,返回成功;

從庫的邏輯變成這樣:

    取消從主庫獲取binlog;

    改爲從本機的BinLogSvr獲取binlog;

因爲BinLogSvr基於paxos協議,binlog到BinLogSvr成功即代表mysql集羣中半數以上的機器已經獲取到最新的日誌,除非半數以上的機器掛掉,纔有可能產生數據不一致;

爲了解決上述的第二個問題,phxsql引入了另外一個插件PhxSqlProxy:

 

實際上, PhxSqlProxy也是一個進程,對前端,模仿了mysql服務端,對後端,模仿了mysql客戶端,將數據庫鏈接請求平等的對應到後端的mysql服務上;

mysql的主庫由BinLogSvr來選舉,基於paxos算法;

若是有sql請求到來,PhxSqlProxy會向BinLogSvr來查詢當前是否爲主庫,若是是主庫,則將請求傳給本機的mysql服務;若是是從庫,則將請求轉給主庫;

 

結束;

主庫掛了或者是租約過時,新的主庫選舉是由BinlogSvr來完成的; 

相關文章
相關標籤/搜索