正文
前面的几篇文章中已经介绍了不少图数据库的基础知识:
从扩线查询能力分析图数据库Titan的设计改进点
一起学图数据库系列:图数据库概述
一起学图数据库系列:图数据库与传统数据库的对比分析
开源图数据库Titan项目已经停止更新,JanusGraph可以说复活了Titan项目,到目前为止,JanusGraph与Titan在核心机制上相差不大。JanusGraph/Titan有如下关键设计:
1. 支持
大规模图数据存储
,Titan图数据库是建立在分布式集群上,数据存储容量和集群节点数量成正比
2. 支持
弹性和线性扩展
,
高可用
,
高容错
3. 支持
Gremlin
图查询语言
4. 支持利用
Hadoop计算框架
对图数据进行分析
5. 支持外部
索引
:ElasticSearch、Solr、Lucene
6. 支持
多储存引擎
:Cassandra、HBase、Berkeley DB和InMemory模式;
7. 基于Apache License 2.0
本文内容以HBase作为Storage Backend,详细介绍JanusGraph的内部数据存储结构。
JanusGraph基本概念
在介绍关系数据的数据存储结构之前,我们先来看一下JanusGraph的基本概念。
同大多数图数据库一样,JanusGraph采用
属性图
进行建模。基于属性图的模型,JanusGraph有如下基本概念:
Vertex Label
:节点的类型,用于表示现实世界中的实体类型,比如"人”,“车”。在JanusGraph中,每一个节点有且只有一个Vertex Label。当不显式指定Vertex Label时,采用默认的Vertex Label。
Vertex
:节点/顶点,用于表示现实世界中的实体对象。
Edge Label
:边的类型,用于表示现实世界中的关系类型,比如“通话关系”,“转账关系”,“微博关注关系”等;
Edge
: 边,用于表示一个个具体的联系。JanusGraph的边都是单向边。如果需要双向边,则通过两条相反方向的单向边组成。JanusGraph不存在无向边。
Property Key
:属性的类型,比如“姓名”,“年龄”,“时间”等。Property Key有Cardinality的概念。Cardinality有SINGLE、LIST和SET三种选项。这三种选项分别用于表示一个Property中,对于同一个Property Key是只允许有一个值、允许多个可重复的值,还是多个不可重复的值。
Property
:属性,用于表示一个个具体的附加信息,采用Key-Value结构。Key就是Property Key,Value就是具体的值。
属性图举例
张三与李四是同事关系,他们从2017年开始成为同事,用属性图表达:
图切割
作为一种分布式图数据库,JanusGraph需要将数据切分存储到多台机器上。
典型的图切割方法有两种: 一种是
按点切割
,另一种是
按边切割
。
按点切割(Vertex-Cut)
按Vertex切割时,切割线通过图的Vertex,而不是Edge。每一条Edge边只保存一次,并且每一条Edge只出现在一台机器上,邻居多的Vertex会被分发到不同的机器上。
按边切割(Edge-Cut)
按Edge切割时,切割线只穿过连接vertex的edge,此时,每一个vertex只保存一次。切断的Edge会保存到多台机器上。
JanusGraph采用的分片方式是按Edge切割,而且是对于每一条边,都会被切断。切断后,该边会在起始Vertex上和目的Vertex上各存储一次。通过这种方式,JanusGraph不管是通过起始Vertex,还是从目的Vertex,都能快速找到对端Vertex。
备注
1. 对于Super Node的存储模式不同,这里暂不展开讨论。
2. JanusGraph允许将Edge Label定义为单向感知的edge. 对于单向感知的edge,只会从起始vertex查询此edge,不会从目的vertex反向查询。因此,这种情况下,目的节点不存储该vertex,仅在起始节点存储。
存储方式
还是以上面的例子为例,按边切割后,变成如下结果:
在JanusGraph中,是点为中心,按切边的方式存储数据的。节点的ID作为HBase的Rowkey,节点上的每一个属性和每一条边,作为该Rowkey的一个个独立的Cell。即每一个属性、每一条边,都是一个个独立的
KCV结构(Key-Column-Value)
。
如下图所示:
备注
简化起见,此处暂不考虑节点中如何记录其所属的Vertex Label。
详细存储格式
Vertex存储格式
1. Vertex ID以Rowkey的形式存储在HBase中,Vertex ID共包含64个bit。
2. Vertex ID由partition id、count、ID padding三部分组成。
3. 最高位5个bit是partition id. partition是JanusGraph抽象出的一个概念。当Storage Backend是HBase时,JanusGraph会根据partition数量,自动计算并配置各个HBase Region的split key,从而将各个partition均匀映射到HBase的多个Region中。然后通过均匀分配partition id最终实现数据均匀打散到Storage Backend的多台机器中。