1. 程式人生 > >圖解Janusgraph系列-圖資料底層序列化原始碼分析(Data Serialize)

圖解Janusgraph系列-圖資料底層序列化原始碼分析(Data Serialize)

# 圖解Janusgraph系列-圖資料底層序列化原始碼分析(Data Serialize) 大家好,我是`洋仔`,JanusGraph圖解系列文章,`實時更新`~ #### 圖資料庫文章總目錄: * **整理所有圖相關文章,請移步(超鏈):**[圖資料庫系列-文章總目錄 ](https://liyangyang.blog.csdn.net/article/details/111031257) * **地址:**[https://liyangyang.blog.csdn.net/article/details/111031257](https://liyangyang.blog.csdn.net/article/details/111031257) > **`原始碼分析相關可檢視github(碼文不易,求個star~)`**: [https://github.com/YYDreamer/janusgraph](https://github.com/YYDreamer/janusgraph) > 下述流程高清大圖地址:[https://www.processon.com/view/link/5f471b2e7d9c086b9903b629](https://www.processon.com/view/link/5f471b2e7d9c086b9903b629) > 版本:JanusGraph-0.5.2 **轉載文章請保留以下宣告:** >作者:洋仔聊程式設計 >微信公眾號:匠心Java >原文地址:[https://liyangyang.blog.csdn.net/](https://liyangyang.blog.csdn.net/) ## 正文 JanusGraph的資料匯入過程主要分為三階段:prepare(準備)、serialize(序列化)、commit(提交);不同階段有不同的作用,如下: ![](https://img2020.cnblogs.com/blog/1252473/202012/1252473-20201217201738774-1331573486.png) 下面我們分別從匯入`vertex`節點和`edge`邊兩部分來分析寫流程 > 建議依據原始碼同步看本文章,便於理解! ## 一:vertex資料寫流程 下面`vertex`節點資料的匯入, ### prepare階段 主要是依據當前給定的引數,組裝出對應的vertex 或者 edge 物件;物件中包含對應的id、索引資訊、屬性資訊和鎖資訊等; 過程中包含以下幾種作用: * 預設新增`vertex exist`屬性,值為true,標識當前節點是否存在 * 預設新增`label edge`邊,標識當前的節點 或者 邊是什麼label * 生成`vertex`、`edge`、`property`的全域性分散式唯一id * 自定義屬性驗證是否滿足唯一性約束 主要流程如下圖(建議依照原始碼一塊檢視,上述github地址已給出): ![](https://img2020.cnblogs.com/blog/1252473/202012/1252473-20201217201843145-988193875.jpg) ### serialize階段 主要是對上述`prepare`階段準備好的資料進行序列化為二進位制資料,為儲存二進位制資料到`backend storage`做準備; 另外獲取本地鎖 + 分散式鎖資料插入(此處只是將資料插入到Hbase,插入成功並不代表獲取成功) 過程中包含以下幾種作用: * 序列化所有`relation`資料並存儲,包含屬性、label edge、normal edge * 獲取屬性對應`index`需要更新的資料,並序列化儲存; 包含`組合索引和mixed index`的處理 * 獲取基於圖例項的本地鎖 * 獲取了本地鎖的前提前,獲取`edge lock` 和 `index lock`分散式鎖(此處的獲取鎖只是將對應的KLV儲存到Hbase中!儲存成功並不代表獲取鎖成功,在commit階段才會去檢查是不是獲取分散式鎖成功!) 主要流程如下圖: ![](https://img2020.cnblogs.com/blog/1252473/202012/1252473-20201217201851005-1444532065.jpg) ### commit階段 主要是獲取`本地鎖`+`分散式鎖`成功後,將對應`序列化`後的資料新增到對應的`backend storage`中;完成圖資料插入過程! 在此階段才會對相簿中的真實資料開始影響,才會涉及到事務的回滾機制; 過程中包含以下幾種作用: * 判斷分散式鎖的狀態,獲取成功則進行資料持久化;不成功則失敗 * 持久化`relation`資料 * 持久化`index`資料,包含組合索引儲存到第三方儲存;`mixed index`儲存到第三方索引庫中 * 刪除對應的本地鎖 和 分散式鎖的佔用 主要流程如下圖: ![](https://img2020.cnblogs.com/blog/1252473/202012/1252473-20201217201856648-1103915696.jpg) ## 二:edge資料寫流程 針對於`edge`的寫資料流程,整體的流程和`vertex`節點的資料寫入相同,有幾點不同,下面一一列出: **1、生成分散式唯一id的過程** 匯入Edge資料在生成edge的唯一id時,`partition id`的獲取不再是`隨機獲取`,而是嘗試獲取邊對應的`out vertex`的`partition id`; id的組成部分也不同,沒有`idPadding`部分; 具體解釋請看:《JanusGraph-分散式id生成策略》文章 **2、在`edge`的匯入中,沒有同`vertex`資料匯入,新增預設的`節點是否存在屬性`和`節點和節點對應label的邊`** **3、獲取`edge`對應的屬性的index update時不同** 在匯入`vertex`資料時,將節點對應的屬性作為relation存放在addRelation中,然後收集所有的屬性relation迴圈獲取index uodate;如下虛擬碼: ```java 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對應的所有屬性進行分別獲取;如下虛擬碼: ```java 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)); } ``` **4、`edge`對應的relation資料,也就是當前插入的這個邊,需要被序列化兩次** 一次是源節點+邊關係,一次是目標節點+邊關係(因為jansugraph是通過edge cut方式儲存圖資料的) **5、`edge`的資料插入過程中,edge的序列化組成部分不同於vertex的序列化組成部分;** 不同點請看《Janusgraph-儲存結構》文章 **6、`edge`的資料插入中,edge的property和vertex的property組成不同!** `edge`中針對於`sort key`和`signature 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邊資料的匯入 上述主要分析了`vertex`和`edge`的資料匯入,大致流程相似;也分析了兩部分匯入資料的差異; 其中涉及的`分散式唯一id`的生成邏輯 和 `鎖機制獲取`的邏輯,請看《圖解Janusgraph系列-Lock鎖機制(本地鎖+分散式鎖)分析》和《圖解Janusgraph系列-分散式id生成策略分析》兩篇文章! 針對於第三方索引的序列化儲存邏輯,邏輯相對簡單,此處沒有給出,具體讀者可以自主分析一下原始碼 > 碼字不易,求個贊