图数据库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/

更多内容请关注每日编程。


分享到:


相關文章: