1. 程式人生 > >基於一致性雜湊的分散式記憶體鍵值儲存——CHKV

基於一致性雜湊的分散式記憶體鍵值儲存——CHKV

Consistent Hashing based Key-Value Memory Storage

基於一致性雜湊的分散式記憶體鍵值儲存——CHKV。

系統設計

  • NameNode : 維護key與節點的對映關係(Hash環),用心跳檢測DataNode(一般被動,被動失效時主動詢問三次),節點增減等系統資訊變化時調整資料並通知Client;
  • DataNode : 儲存具體的資料,向NameNode主動發起心跳並採用請求響應的方式來實現上下線,便於NameNode挪動資料
  • Client : 負責向NameNode請求DataNode資料和Hash演算法等系統資訊並監聽其變化,操縱資料時直接向對應DataNode發起請求就行,暫時只包含set,get,delete三個操作

NameNode失效則整個系統不可用

若當成記憶體資料庫使用,則只要有一個 DataNode 失效(未經請求與資料轉移就下線了)
整個系統就不可對外服務;
若當成記憶體快取使用,則 DataNode 失效只是失去了一部分快取,系統仍然可用。

客戶要使用CHKV就必須使用Client庫或者自己依據協議(相容redis)實現,可以是多種語言的API。

分析

要想實現高可用有兩點: NameNode 要主從雙機熱備,避免單點失效;每個 DataNode 可以做成主從複製甚至叢集。

各個元件之間的連線情況:

  • NameNode 要保持和 N 個 Client 的TCP長連線,但是隻有在叢集發生變化時才有互動,所以使用IO多路複用負載就不大
  • NameNode 要和 M 個 DataNode 保持心跳,TCP請求響應式,負載與 M 和心跳間隔秒數 interval 有關
  • DataNode 與 Client 是TCP請求響應式操作,操作結束斷開連線,也可以考慮加入連線池
  • DataNode 與 NameNode 保持心跳
  • Client 與 NameNode 保持TCP長連線
  • Client 與 DataNode TCP請求響應式操作

如下圖所示,有4個連線,其中1、2要保持連線,3、4完成請求後就斷開連線

                     NameNode
                   ||       ||     
  1
、心跳請求響應|| ||2、監聽長連線 || 3、資料請求響應 || DataNodes ========== Clients || || || 4、資料轉移,可複用3

開發優先順序:3、1、4、2

具體效能瓶頸要結合壓測來分析

使用方法

DataNode 執行起來就可以直接使用 redis-cli 連線,如redis-cli -h 127.0.0.1 -p 10100,並進行set、get、del操作;

注意:現在必須首先執行 NameNode,然後通過JVM引數的方式調整埠,可以在同一臺機器上執行多個 DataNode
若要在不同機器上執行 DataNode 則可以直接修改配置檔案

新的DataNode可以直接上線,NameNode會自動通知下一個節點轉移相應資料給新節點;DataNode若要下線,
則可以通過telnet DataNode 節點的下線監聽埠(TCP監聽) 如 telnet 127.0.0.1 6666 ,
併發送 k 字元即可,待下線的DataNode收到命令 k 後會自動把資料全部轉移給下一個DataNode
然後提示程序pid,使用者就可以關閉該DataNode程序了,如 Linux: kill -s 9 23456Windows:taskkill /pid 23456

NameNode和DataNode啟動後就可以使用Client了,程式碼示例如下:

    try(Client client = new Client("192.168.0.136","10102")){
        logger.debug(client.set("192.168.0.136:10099","123456")+"");
        logger.debug(client.get("192.168.0.136:10099")+"");
        logger.debug(client.set("112","23")+"");
        logger.debug(client.del("1321")+"");
        logger.debug(client.del("112")+"");
    }

程式碼結構

  • NameNode : 實現 NameNode 功能
    • handler : handler
    • res : 資源,如常量,命令工廠
    • service : 服務,含Client管理,DataNode管理
  • DataNode : 實現 DataNode 功能
    • command : 處理客戶端各個命令的具體命令物件
    • job : 一些的任務如心跳、資料遷移
    • handler : 處理連線的handler
    • service : 服務,含定時任務管理,資料請求管理
  • Client : 實現 Client 功能
    • handler : handler
    • Client : 暴露給使用者的命令管理
    • Connection : 發出網路請求
  • Common : 實現一些公共的功能,上面三個模組依賴於此模組
    • command : 命令抽象類
    • model : 一些公用的pojo,如請求響應物件
    • util : 一些工具類
    • helper : 輔助指令碼

水平有限,目前專案的問題還很多,可以列個清單:

  • 高可用性保證
  • 斷線重連
  • DataNode遷移資料的完整性保證
  • 遷移過程資料的一致性
  • 對於WeakReference的支援
  • 更多資料型別
  • 更多操作
  • 完整的校驗機制
  • 等等……

全部程式碼在Github上,歡迎 star,歡迎 issue,歡迎 pull request……
總之就是歡迎大家和我一起完善這個專案,一起進步。