高性能nosql ledisdb設計與實現 (2):replication

ledisdb現在已經支持replication機制,爲ledisdb的高可用做出了保障。

使用

假設master的ip爲10.20.187.100,端口6380,slave的ip爲10.20.187.101,端口爲6380.

首先我們需要master打開binlog支持,在配置文件中指定:

use_bin_log : true

在slave的機器上面我們可以通過配置文件指定slaveof開啓replication,或者通過命令slaveof顯示的開啓或者關閉。

slaveof 10.20.187.100 6380

ledisdb的replication機制參考了redis以及mysql的相關實現,下面簡單說明。

redis replication

redis的replication機制主要介紹在這裏,已經說明的很詳細了。

  • slave向master發送sync命令
  • master將其當前的數據dump到一個文件,同時在內存中緩存新增的修改命令
  • 當數據dump完成,master就將其發送給slave
  • slave接受完成dump數據之後,將其本機先前的數據清空,然後在導入dump的數據
  • master再將先前緩存的命令發送給slave

在redis2.8之後,爲了防止斷線導致重新生成dump,redis增加了psync命令,在斷線的時候master會記住當前的同步狀態,這樣下次就能進行斷點續傳了。

mysql replication

mysql的replication主要是通過binlog的同步來完成的。在master的任何數據更新,都會寫入binlog,至於binlog的格式這裏不再累述。

假設binlog的basename爲mysql,index文件名字爲mysql-bin.index,該文件記錄着當前所有的binlog文件。

binlog有max file size的配置,當binlog寫入的的文件大小超過了該值,mysql就會生成一個新的binlog文件。當mysql服務重啓的時候,也會生成一個新的binlog文件。

在Percona的mysql版本中,binlog還有一個max file num的設置,當binlog的文件數量超過了該值,mysql就會刪除最早的binlog。

slave有一個master.info的文件,用以記錄當前同步master的binlog的信息,主要就是當前同步的binlog文件名以及數據偏移位置,這樣下次重新同步的時候就能從該位置繼續進行。

slave同步的數據會寫入relay log中,同時在後臺有另一個線程將relay log的數據存入mysql。

因爲master的binlog可能刪除,slave同步的時候可能會出現binlog丟失的情況,mysql通過dump+binlog的方式解決,其實也就是slave完全的dump master數據,在生成的dump中也同時會記錄當前的binlog信息,便於下次繼續同步。

ledisdb replication

ledisdb的replication機制參考了redis以及mysql,支持fullsync以及增量sync。

master沒有采用aof機制,而是使用了binlog,通過指定max file size以及max file num用來控制binlog的總體大小,這樣我就無需關心aof文件持續增大需要重新rewrite的過程了。

binlog文件名格式如下:

ledis-bin.0000001
ledis-bin.0000002

binlog文件名的後綴採用數字遞增,後續我們使用index來表示。

slave端也有一個master.info文件,因爲ledisdb會嚴格的保證binlog文件後綴的遞增,所以我們只需要記錄當前同步的binlog文件後綴的index即可。

整個replication流程如下:

  • 當首次同步或者記錄的binlog信息因爲master端binlog刪除導致不一致的時候,slave會發送fullsync進行全同步。
  • master收到fullsync信息之後,會將當前的數據以及binlog信息dump到文件,並將其發送給slave。
  • slave接受完成整個dump文件之後,清空所有數據,同時將dump的數據導入leveldb,並保存當前dump的binlog信息。
  • slave通過sync命令進行增量同步,sync命令格式如下:

      sync binlog-index binlog-pos
    

    master通過index定位到指定的binlog文件,並seek至pos位置,將其後面的binlog數據發送給slave。

  • slave接收到binlog數據,導入leveldb,如果sync沒有收到任何新增數據,1s之後再次sync。

對於最後一點,最主要就是一個問題,即master新增的binlog如何讓slave進行同步。對於這點無非就是兩種模型,push和pull。

對於push來說,任何新增的數據都能非常及時的通知slave去獲取,而pull模型爲了性能考慮,不可能太過於頻繁的去輪詢,略有延時。

mysql採用的是push + pull的模式,當binlog有更新的時候,僅僅通知slave有了更新,slave則是通過pull拉取實際的數據。但是爲了支持push,master必須得維持slave的一些狀態信息,這稍微又增加了一點複雜度。

ledisdb採用了非常簡單的一種方式,定時pull,使用1s的間隔,這樣既不會因爲輪詢太過頻繁導致性能開銷增大,同時也能最大限度的減少當機數據丟失的風險。

總結

ledisdb的replication機制纔剛剛完成,後續還有很多需要完善,但足以使其成爲一個高可用的nosql選擇了。

ledisdb的網址在這裏https://github.com/siddontang/ledisdb,希望感興趣的童鞋共同參與。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章