圖資料庫JanusGraph介紹

背景:JanusGraph是Titan的一個fork。Titan項目創建於2012年,於2016年停止維護,是一個方便拓展的圖數據庫,支持HBase、Cassandra等作為後端(BerkleyDB不提了),ES、Lucene等做全文索引,以TinkerPop作為圖的查詢和計算框架。2017年,JanusGraph項目fork了Titan,到目前已經推出了0.2.0版本。

圖數據庫JanusGraph介紹

JanusGraph是一個開源的分佈式圖數據庫。它具有很好的擴展性,通過多機集群可支持存儲和查詢數百億的頂點和邊的圖數據。JanusGraph是一個事務數據庫,支持大量用戶高併發地執行復雜的實時圖遍歷。

特性:

支持數據和用戶增長的彈性和線性擴展;

通過數據分發和複製來提過性能和容錯;

支持多數據中心的高可用和熱備份;

支持ACID 和最終一致性;

支持多種後端存儲:

Apache Cassandra

Apache HBase

Google Cloud Bigtable

Oracle BerkeleyDB(僅供測試環境)

支持全局的圖數據分析,報表以及和如下大數據平臺的ETL集成:

Apache Spark

Apache Giraph

Apache Hadoop

支持geo, 數值範圍以及通過如下工具進行全文檢索:

ElasticSearch

Apache Solr

Apache Lucene

支持與Apache TinkerPop圖棧進行原生集成:

Gremlin 圖查詢語言

Gremlin 圖服務器

Gremlin 應用

可以通過如下工具來可視化存儲在JanusGraph中的圖數據:

Cytoscape

Apache TinkerPop的Gephi插件

Graphexp

KeyLines by Cambridge Intelligence

Linkurious

### JaunsGraph數據模型

JanusGraph採用鄰接表(adjacency list)的方式存儲圖,也即圖以頂點(vertex)和其鄰接表組成。

鄰接表中保存某個頂點的所有入射邊(incident edges)。

通過將圖採用鄰接表的形式存儲,JanusGraph確保了某個頂點的所有入射邊和屬性都被緊湊的存儲在一起,從而能夠加快遍歷速度,缺點是數據存儲了兩次。而且JanusGraph以sort key指定的順序存儲數據。

JanusGraph可以採用任何支持big table數據模型的存儲後端存儲鄰接表。

JanusGraph將每個鄰接表作為以個row保存在存儲後端,64位的vertex id是指向鄰接表的key。

每個邊和屬性都是作為獨立的cell保存的,以實現更高效插入和刪除。每行中最大能保存的cell的個數,也就是vertex的edge的數量限制。

vertex id ---- cell,cell,cell……

cell --- 一個cell是由列和值組成的,每個edge和property都作為鄰接表的一個cell存儲

### JanusGraph支持兩種類型的索引:graph index和vertex-centric index。

graph index常用於根據屬性查詢Vertex或Edge的場景;

vertex index在圖遍歷場景非常高效,尤其是當Vertex有很多Edge的情況下。

JanusGraph支持兩種不同的Graph Index,Composte(複合) index和Mixed(混合) Index;

通過JanusGraph的management操作的:

JanusGraphManagement.buildIndex(String,Class)

第一個參數是index的名稱,第二個參數是要索引的類(如Vertex.class)

注意:如果沒有建索引,會進行全表掃面,此時性能非常低,可以通過配置force-index參數禁止全表掃描。Mixed index效率要比Composite Index低。

### JanusGraph中的事務

graph.V()即會開啟一個事務,graph.commit()則會提交一個事務。用戶也可以使用graph.newTransaction()獲取對事務的控制權。

事務在commit()或數據庫shutdown()時才結束。

對JanusGraph的每個操作都是在事務執行,無需顯式聲明,由第一次操作開啟。

### JanusGraph的schema及數據建模

每個JanusGraph都有一個schema,該schema由edge labels, property keys和vertex labels組成。

在JanusGraph中,一個Graph用於一個schema。

定義schema

def defineGratefulDeadSchema(janusGraph) {

m = janusGraph.openManagement()

person = m.makeVertexLabel("person").make()

birth = m.makePropertyKey("birth").dataType(Date.class).make()

age = m.makePropertyKey("age").dataType(Integer.class).make()

name = m.makePropertyKey("name").dataType(String.class).make()

index = m.buildIndex("nameCompositeIndex", Vertex.class).addKey(name).unique().buildCompositeIndex()

m.commit()

}

{"id":4700,"label":"person","properties":{"name":[{"id":"171-38o-5j9","value":"fu2 "}],"birth":[{"id":"1zh-38o-3yd","value":1509043638976}],"age":[{"id":"1l9-38o-4qt","value":1}]}}

### 安裝部署:centos 7 64bit,存儲後端為Hbase 1.3.1,Java取1.8.0_171,ElasticSearch;

JanusGraph通過gremlin-server提供服務,默認後端使用HBase+ElasticSearch。

Java8環境

安裝hadoop和hbase

安裝ES

安裝janusgraph

下載:https://github.com/JanusGraph/janusgraph/releases

janusgraph-0.2.1-hadoop2.zip

unzip ~/janusgraph-0.2.1-hadoop2.zip

cd janusgraph-0.2.1-hadoop2/

cp conf/janusgraph-hbase-es.properties conf/gremlin-server/janusgraph-hbase-es-server.properties

添加gremlin.graph=org.janusgraph.core.JanusGraphFactory

cp conf/gremlin-server/gremlin-server.yaml conf/gremlin-server/socket-gremlin-server.yaml

cp conf/gremlin-server/gremlin-server.yaml conf/gremlin-server/http-gremlin-server.yaml

修改 socket-gremlin-server.yaml

// host和port不爽也可以改,默認8182

graphs: {

graph: conf/gremlin-server/janusgraph-hbase-es-server.properties

}

channelizer: org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer

修改 http-gremlin-server.yaml

// port一定不要和websocket模式的衝突了…… 我設置的8183

graphs: {

graph: conf/gremlin-server/janusgraph-hbase-es-server.properties

}

channelizer: org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer

啟動server

bin/gremlin-server.sh ./conf/gremlin-server/socket-gremlin-server.yaml

bin/gremlin-server.sh ./conf/gremlin-server/http-gremlin-server.yaml

補充:

Gremlin控制檯解釋器使用的是Apache Groovy

默認情況下,JanusGraph使用Berkeley DB作為後端存儲引擎,使用Elasticsearch作為索引引擎。

如果配置JanusGraph集群, 需要定義存儲後臺. JanusGraphFactory接受一個分號分割的字符串, 分號前是存儲後臺類型的名稱, 分號後是主機名稱或者是目錄

graph = JanusGraphFactory.open('cassandra:localhost')

graph = JanusGraphFactory.open('berkeleyje:/tmp/graph')

Gremlin是一種函數式數據流語言,可以使得用戶使用簡潔的方式表述複雜的屬性圖(property graph)的遍歷或查詢。

每個Gremlin遍歷由一系列步驟(可能存在嵌套)組成,每一步都在數據流(data stream)上執行一個原子操作。

Gremlin包括三個基本的操作:

map-step

對數據流中的對象進行轉換;

filter-step

對數據流中的對象就行過濾;

sideEffect-step

對數據流進行計算統計;

參考文獻:

https://docs.janusgraph.org/latest/

更多內容請關注每日編程。


分享到:


相關文章: