TitanDB/JanusGraph圖數據庫入門簡介|實戰總結|選型對比|存儲結構深入分析

歷史背景

JanusGraph圖數據庫,源自於TitanDB開源圖數據庫。TitanDB在2012年發佈第一個版本,2015年被Datastax公司收購,後續不再維護導致項目停滯。

 

圖數據庫有2個最具代表性的查詢語言:Cypher 及 Gremlin。Cypher是商業公司Neo4j出品,Neo4j圖數據庫在2007年發佈了第一個版本,是商用圖數據庫領域的開拓者。Gremlin是Apache TinkerPop框架下規範的語言,TinkerPop屬於當前圖數據庫領域最流行的框架規範,具備開源開放、功能豐富、生態完善等特點,擁有大量廠商支持(超過20家),Titan當屬TinkerPop框架下最成功的開源圖數據庫實現,後續的不少圖數據庫或多或少借鑑了Titan的思想,Titan的幾位核心作者包括:Dan、Matthias、Marko(okram)、Stephen(spmallette)等,其中的兩位--Marko和Stephen同時也是TinkerPop的核心作者。個人在此致敬Titan和TinkerPop。

 

非常令人遺憾的是,Titan在2015年被收購後,其開源社區無人維護,否則以其前三年的勢頭來看,大有一統圖江湖的趨勢,不過沒有如果。而Janus稍許彌補了這個遺憾,也算是後繼之人,但是Janus絕大部分功能沿襲自Titan,沒有更上一個臺階發揚光大,只是做了一些小修補。下面是對Titan/Janus的一些總結和分析。

 

2016年由其他人基於Titan源碼Fork出了Janus,到目前(2020年)Janus已經合入了700多個Pull Request,主要包括:

  • 支持Bigtable後端;

  • 跟進TinkerPop框架的版本升級,目前已支持3.4.4;

  • 後端存儲升級與兼容,比如兼容Apache Cassandra 3.x, Apache HBase 2.x;

  • 其它方面的增強與Bugfix,比如:新增Schema約束、新增HBase TTL、豐富GEO索引查詢、優化AdjacentID查詢等。

總結來說,在大方向上Janus對Titan改進並不多,主要包括2方面:

  • 提供後端存儲的版本升級與兼容適配;

  • 新增極少的新Feature,大多是小修補,有少量功能增強。

 

整體架構

Janus整體架構分爲3層,中間層是圖引擎,最底層是存儲層,最上層是應用程序層:

  • 圖引擎:圖數據庫核心,對外提供圖方式的讀寫API。處理寫請求,將數據索引起來、按照特定的格式寫到存儲層;處理讀請求,按照特定格式從存儲層高效讀取數據,組裝成圖結果返回上層。

  • 存儲層:用於持久化圖數據,包括兩方面數據:1、圖數據(包括頂點和邊),存儲在Storage Backend裏面,可以選擇配置一種後端存儲,比如Cassandra或HBase;2、Mixed模糊索引數據(包括範圍索引和全文索引等),存儲在External Index Backend裏面,也可以選則配置一種後端存儲,比如ES或Solr;如果不開啓Mixed模糊索引,則無需配置索引後端。

  • 應用層:業務程序可以有兩種方式來使用:1、內嵌到程序中,與業務程序共用同一個進程JVM;2、以服務的方式單獨啓動,業務程序通過HTTP API來訪問。

 

數據模型/存儲結構(整體)

圖概念簡介:圖的核心是頂點和邊,頂點代表現實世界中的實體,邊代表現實世界中的關係,“我喜歡你”就可以抽象爲兩個頂點和一條邊,同時頂點和邊還可以有屬性。

圖是如何被存儲的?在Titan/Janus中,使用的是鄰接表存儲結構(見上圖,另一種流行的結構是Neo4j的十字鏈表)。比對着上圖來詳細看:Janus把每個頂點的數據存爲一行,當插入圖數據時,會爲每個頂點分配一個遞增的Long類型ID(vertex id),查詢的時候使用這個ID來進行索引查找。頂點的數據包括兩方面內容:頂點屬性(property)和鄰接邊(edge),每個頂點屬性存爲一列,每條鄰接邊也存爲一列,列內部的詳細結構見下一部分。

 

數據模型/存儲結構(邊及屬性)

一個頂點的各頂點屬性和邊數據是按照順序排列的,內部規則如下:

  • 頂點屬性:每個頂點屬性包括:屬性類型(key id)、屬性ID(property id)、屬性值(property value),各頂點屬性按照屬性類型的順序依次存儲。

  • 邊數據:邊複雜一些,這裏簡化下講最重點的核心思想,每條鄰接邊包括:邊類型(label id)、邊終點(adjacent vertex id)、邊屬性(other properties),各鄰接邊按照邊類型+邊終點組合的順序依次存儲。

 

Janus這種存儲結構的優點是:

  • 1、可以高效的查詢一個點的鄰接邊:當需要查詢一個頂點的所有鄰接邊時,先通過該頂點的ID快速定位到某一行,然後對這一行內的所有列依次讀取,高效返回數據。

  • 2、可以高效的查詢一個超級點的小部分鄰接邊:如果只需要查詢一個頂點的某種類型的鄰接邊時,可以根據邊類型進行條件篩選,忽略掉其它類型的鄰接邊,加快讀取速度。

針對上述第2個場景,十字鏈表的存儲結構是難於進行類似性能優化的。因此當一個頂點的鄰接邊超多時,即使用戶只需要查詢其部分鄰接邊,也還是需要從磁盤先讀取所有鄰接邊,從而導致性能低下。

 

Janus大功能總結

  • 支持Gremlin圖語言,完全兼容TinkerPop框架;

  • 支持4種後端存儲:Cassandra、HBase、Bigtable、Berkeley;(此處Bigtable是Janus v0.1.0的增強)

  • 支持嚴格的Schema元數據校驗和豐富的數據類型;(此處是Janus v0.3.0的增強)

  • 支持事務Transaction,是ThreadLocal隔離級別(個人理解爲RC級),不保證ACID,嚴格的事務需要後端存儲保證,Cassandra、HBase兩個後端可支持最終一致性;

  • 支持緩存Cache,有2種類型的緩存:

    • 1、事務內緩存,生命週期和作用範圍均在一個事務以內,包括`Vertex(adjacency) Cache`和`Index Cache`,可設置大小;

    • 2、全局緩存,生命週期可超過事務,可設置大小和超時時間;

  • 支持多節點部署服務,不過緩存同步是個問題,並不會被集羣自動管理,需要靠緩存超時來減輕數據不一致;

  • 支持圖分區,除支持邊切割之外,還支持supernode點內切割,點切割可以指定分區在一個VertexLabel上(how?);

  • 支持TTL:支持頂點、邊、屬性的TTL;(此處HBase TTL部分是Janus v0.2.1的增強,詳見#356)

  • 支持Vertex-Centric索引,可以有效緩解超級點的查詢性能問題;

  • 支持二級索引(Composite Index),原生支持,加速如下查詢:根據屬性值精確匹配來查詢頂點或邊;

  • 支持範圍索引(Mixed Index),需要依賴第三方索引庫如ES,支持查詢方式包括:等於、大於、小於等;

  • 支持全文索引(Mixed Index),需要依賴第三方索引庫如ES,支持查詢方式包括:textContains、textContainsPrefix、textContainsRegex、textContainsFuzzy、textPrefix、textRegex、textFuzzy。

  • 支持空間位置索引,需要依賴第三方索引庫,支持查詢方式包括:geoIntersect、geoDisjoint、geoWithin、geoContains;(此處除geoWithin之外的方式是Janus v0.2.0的增強,詳見#79)

  • 支持單向邊,只允許往out-going方向進行遍歷;

  • 可動態創建圖實例。

     

Janus官方公佈的技術限制:

  1. 最大支持2^60條邊。

  2. 雖然允許定義Object類型,但是爲了性能考慮,依然建議定義確切的類型。

  3. 根據ID獲取一條邊時,代價是O(log(k)),與鄰接點的關聯鄰接邊數量有關。(注:感覺官網說的有錯誤,理論上應該是與邊的總數有關,代價是O(log(N))比較合理)

  4. 併發刪除與更新操作,可能導致殘留頂點的部分屬性或邊。

  5. 邊不允許在跨事務中使用,包括創建或查詢出來的邊。

 

Janus實戰問題總結:

  1. 只允許自動生成ID,不支持主鍵ID或用戶自定義ID。當數據規模達到10億並有大量覆蓋寫需求時,需要建立索引並在寫之前進行大量隨機讀操作,導致整體性能嚴重降低。

  2. 大規模數據讀取,返回大量查詢結果時會爆內存,無法將全量數據讀到客戶端。

  3. 頂點的 [屬性]列表 和 [鄰接邊]列表 兩種數據存在一起(cells in a row),頂點和邊讀寫性能相互影響嚴重。

  4. 頂點屬性存爲多個列(cell),其實並不利於OLTP查詢性能,寫入的KV對數量也增大若干倍。

  5. 邊和屬性存儲了多餘的ID,屬性ID和邊ID實際作用不大。

  6. 忽視後端存儲的區別,所有的後端都當成是KV存儲,使用大一統的序列化封裝,以至於大部分默認的操作把整個頂點的鄰接邊和屬性都讀出來,浪費了IO資源、代價很大。

  7. 沒有針對性的根據後端存儲進行優化,比如數據類型、查詢/計算下推等優化。

  8. 模糊索引依賴ES、Solr等外部系統,存在運維問題和雙寫問題。具體而言,部署運維麻煩,數據量大的時候問題很多,需要依賴ES專業人員調優;雙寫則引入額外問題,比如:數據一致性、圖和索引兩種後端性能不匹配、數據同步與穩定性等問題。(如:Vertex TTL does not remove indexed value from ES mixed index #987 )

  9. 元數據與索引的創建方式略複雜,配置項過多也導致運維難度增大。

  10. 缺少常用的圖算法庫,比如路徑搜索、相似性等算法。

  11. 缺少導入數據、可視化界面、備份恢復等工具鏈。有一些第三方工具可供集成,但配置和使用起來都不是很友好。

 

面對這些問題,我們是如何解決的?請聽下回分解。

 

原文鏈接:https://zhuanlan.zhihu.com/p/112266974


Janus參考資料:

配置項文檔:

https://docs.janusgraph.org/basics/configuration-reference/

 

技術限制:

https://docs.janusgraph.org/basics/technical-limitations/

https://docs.janusgraph.org/basics/common-questions/

 

數據類型支持:

https://docs.janusgraph.org/index-backend/search-predicates/#data-type-support

https://docs.janusgraph.org/basics/schema/

 

索引介紹:

https://docs.janusgraph.org/index-management/index-performance/

https://docs.janusgraph.org/index-backend/search-predicates/

 

數據模型:

https://docs.janusgraph.org/advanced-topics/data-model/

 

高級特性:

https://docs.janusgraph.org/advanced-topics/advschema/

 

第三方可視化界面集成:

Arcade Analytics, Cytoscape, Gephi plugin for Apache TinkerPop, Graphexp, Key Lines by Cambridge Intelligence, Linkurious and Tom Sawyer Perspectives.

 

Janus版本增強:

https://github.com/JanusGraph/janusgraph/blob/master/docs/changelog.md

https://github.com/JanusGraph/janusgraph/milestone/1?closed=1

 

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