圖解Janusgraph系列-圖數據底層序列化源碼分析(Data Serialize)

圖解Janusgraph系列-圖數據底層序列化源碼分析(Data Serialize)

你們好,我是洋仔,JanusGraph圖解系列文章,實時更新~java

圖數據庫文章總目錄:

源碼分析相關可查看github(碼文不易,求個star~)https://github.com/YYDreamer/janusgraphgit

下述流程高清大圖地址:https://www.processon.com/view/link/5f471b2e7d9c086b9903b629github

版本:JanusGraph-0.5.2數據庫

轉載文章請保留如下聲明:編程

做者:洋仔聊編程
微信公衆號:匠心Java
原文地址:https://liyangyang.blog.csdn.net/api

正文

JanusGraph的數據導入過程主要分爲三階段:prepare(準備)、serialize(序列化)、commit(提交);不一樣階段有不一樣的做用,以下:緩存

下面咱們分別從導入vertex節點和edge邊兩部分來分析寫流程微信

建議依據源碼同步看本文章,便於理解!分佈式

一:vertex數據寫流程

下面vertex節點數據的導入,工具

prepare階段

主要是依據當前給定的參數,組裝出對應的vertex 或者 edge 對象;對象中包含對應的id、索引信息、屬性信息和鎖信息等;

過程當中包含如下幾種做用:

  • 默認添加vertex exist屬性,值爲true,標識當前節點是否存在
  • 默認添加label edge邊,標識當前的節點 或者 邊是什麼label
  • 生成vertexedgeproperty的全局分佈式惟一id
  • 自定義屬性驗證是否知足惟一性約束

主要流程以下圖(建議依照源碼一塊查看,上述github地址已給出):

serialize階段

主要是對上述prepare階段準備好的數據進行序列化爲二進制數據,爲存儲二進制數據到backend storage作準備; 另外獲取本地鎖 + 分佈式鎖數據插入(此處只是將數據插入到Hbase,插入成功並不表明獲取成功)

過程當中包含如下幾種做用:

  • 序列化全部relation數據並存儲,包含屬性、label edge、normal edge
  • 獲取屬性對應index須要更新的數據,並序列化存儲; 包含組合索引和mixed index的處理
  • 獲取基於圖實例的本地鎖
  • 獲取了本地鎖的前提早,獲取edge lockindex lock分佈式鎖(此處的獲取鎖只是將對應的KLV存儲到Hbase中!存儲成功並不表明獲取鎖成功,在commit階段纔會去檢查是否是獲取分佈式鎖成功!)

主要流程以下圖:

commit階段

主要是獲取本地鎖+分佈式鎖成功後,將對應序列化後的數據添加到對應的backend storage中;完成圖數據插入過程! 在此階段纔會對圖庫中的真實數據開始影響,纔會涉及到事務的回滾機制;

過程當中包含如下幾種做用:

  • 判斷分佈式鎖的狀態,獲取成功則進行數據持久化;不成功則失敗
  • 持久化relation數據
  • 持久化index數據,包含組合索引存儲到第三方存儲;mixed index存儲到第三方索引庫中
  • 刪除對應的本地鎖 和 分佈式鎖的佔用

主要流程以下圖:

二:edge數據寫流程

針對於edge的寫數據流程,總體的流程和vertex節點的數據寫入相同,有幾點不一樣,下面一一列出:

一、生成分佈式惟一id的過程

導入Edge數據在生成edge的惟一id時,partition id的獲取再也不是隨機獲取,而是嘗試獲取邊對應的out vertexpartition id; id的組成部分也不一樣,沒有idPadding部分;

具體解釋請看:《JanusGraph-分佈式id生成策略》文章

二、在edge的導入中,沒有同vertex數據導入,添加默認的節點是否存在屬性節點和節點對應label的邊

三、獲取edge對應的屬性的index update時不一樣

在導入vertex數據時,將節點對應的屬性做爲relation存放在addRelation中,而後收集全部的屬性relation循環獲取index uodate;以下僞代碼:

for (InternalRelation add : Iterables.filter(addedRelations,filter)) {        
	if (add.isProperty()) mutatedProperties.put(vertex,add); // 此處只操做屬性類型的
    mutations.put(vertex.longId(), add);
}
// 此處,收集節點對應屬性對應的索引須要更新的數據、增長或刪除節點時纔有做用; 針對於插入edge的操做,不涉及此處
for (InternalVertex v : mutatedProperties.keySet()) {
    indexUpdates.addAll(indexSerializer.getIndexUpdates(v,mutatedProperties.get(v)));
}

而在edge數據導入中,只將edge這條邊做爲relation插入到addRelation中,因此沒法獲取屬性relation,轉而經過收集過程當中,對每一個edge對應的全部屬性進行分別獲取;以下僞代碼:

for (InternalRelation add : Iterables.filter(addedRelations,filter)) {
	if (add.isProperty()) mutatedProperties.put(vertex,add); // 此處只操做屬性類型的
    mutations.put(vertex.longId(), add);
    // 獲取邊包含的屬性;在節點插入時沒有做用,插入邊數據時,獲取邊上的屬性對應的索引; 只有edge操做中包含邊屬性,而且包含索引!
    indexUpdates.addAll(indexSerializer.getIndexUpdates(add));
}

四、edge對應的relation數據,也就是當前插入的這個邊,須要被序列化兩次

一次是源節點+邊關係,一次是目標節點+邊關係(由於jansugraph是經過edge cut方式存儲圖數據的)

五、edge的數據插入過程當中,edge的序列化組成部分不一樣於vertex的序列化組成部分;

不一樣點請看《Janusgraph-存儲結構》文章

六、edge的數據插入中,edge的property和vertex的property組成不一樣!

edge中針對於sort keysignature key配置的屬性,只將property value存儲在對應位置。其餘未被配置的屬性值包含proeprty key label id + property value

不一樣於vertex數據中的屬性組成包含:proeprty key label id + property 惟一id +property value

三:源碼分析

源碼分析已經push到github:https://github.com/YYDreamer/janusgraph

數據寫入的流程源碼過多,就不在文章中給出分析了,具體請看github中源碼分析註釋吧

四:應用

基於數據序列化導入的源碼博主將圖數據的序列化邏輯抽取出來,生成一個工具包;

主要用於圖數據的遷移和圖數據庫的初始化,適用於大數據量的導入,主要流程以下:

  1. 生成schema到圖中
  2. 獲取schema信息,緩存到內存中
  3. 調用api佔用對應的id blocker,用於離線數據的分佈式惟一id生成
  4. 調用抽取的序列化邏輯序列化節點和邊數據
  5. 生成Hfile
  6. 將hfile導入到Hbase中

上述流程已經通過嚴格的驗證並在生產環境中使用,具體以後會再出一篇文章介紹一下詳細的設計與流程

五:總結

對於JanusGraph圖數據的寫入,主要分爲3部分:

  • schema的建立
  • vertex節點數據的導入
  • edge邊數據的導入

上述主要分析了vertexedge的數據導入,大體流程類似;也分析了兩部分導入數據的差別;

其中涉及的分佈式惟一id的生成邏輯 和 鎖機制獲取的邏輯,請看《圖解Janusgraph系列-Lock鎖機制(本地鎖+分佈式鎖)分析》和《圖解Janusgraph系列-分佈式id生成策略分析》兩篇文章!

針對於第三方索引的序列化存儲邏輯,邏輯相對簡單,此處沒有給出,具體讀者能夠自主分析一下源碼

碼字不易,求個贊和star~

相關文章
相關標籤/搜索