图数据库Titan在生产环境中的使用全过程+分析

来源:互联网 发布:手机照片编辑软件 编辑:程序博客网 时间:2024/04/28 10:05

注:本文以Hbase作为backend,并以下图为例


0、数据模型

Titan在Hbase中的存储结构

Table “名称:titan”

 

Column Family 1:e

CF2:?

Column:

’knows’的ID+IN+点1的ID+边8的ID

Column:

’created’的ID+OUT+点3的ID+边11的ID

Column:

’created’的ID+OUT+点5的ID+边10的ID

Column :

’name’的ID

Column :

’age’的ID

 

 

RowKey

 

v1的ID

Weight=1.0

Weight=0.4(字符串?)

Weight=1.0

Name=”josh”

Age=32

 

 

 

上面的RowKey和ColumnKey都是合成的,实际存成HBase的字符数组中,所以直接查看只能看到二进制串,必须知道相应格式才能解析出来。例如边的ColumnKey中有个表示方向的标记IN或OUT,代码中是这样的:



1、创建一个图

<pre name="code" class="java">// Gremlinconf = new BaseConfiguration();conf.setProperty("storage.backend","hbase");conf.setProperty("storage.hostname","77.77.77.77,77.77.77.78");conf.setProperty("storage.tablename","graph1");g = TitanFactory.open(conf);

上图语句创建了一个名为graph1的图,注意这里的
setProperty("storage.tablename","graph1");
在cassandra里是storage.keyname。使用这种方式可以创建多个图,每个图在Hbase中对应一个大表,表名和图的名字一致。下次如果open的还是这个名字,则相当于打开已有的图,否则就是新创建一个新图。


创建图时其他属性信息参见Titan的官方文档:https://github.com/thinkaurelius/titan/wiki/Using-HBase


2、插入节点

比如,v1,属性为name=‘marko’,age=29
插入语句为
g.addVertex([name:"marko", age:29]);

那么Titan是如何执行这条语句的呢?即如何把点v1放入到本文开头描述的hbase的数据模型中呢?

首先Titan需要生成v1的ID,即rowkey。(如何生成呢:VertexIDAssigner负责分配,IDAuthority做一致性检查返回一个可以分配的ID block, IDPlacementStrategy处理ID分配策略, IDManager根据结点类型添加不同的位标记。不同的Titan Instance会从backend里读出数据确保全局ID)。下图是rowkey的结构。



接下来,Titan把v1的各个属性放到名称为e的column family中,这里v1的属性为name和age,对应的columnkey为name的ID和age的ID,然后把对应的值填入到value中,即name=marko和age=32。

如果对name建了索引怎么办呢?如何插入索引?

现在,如果想再插入一条边:
g.addEdge(g.v(1),g.v(4),"created",[weight:23]);

Titan是如何把这条边放入到hbase的数据模型中的呢?

首先从图中读取ID为1和ID为4的两个结点,接下来就是对Rowkey为1和4的两个行进行写入操作。在HBase的大表中专门有一行保存了边和点的属性名和id的对应关系。如果图g中已经有了Label为“created”的边,就在该行中找到该Label的ID。否则新建一个新的ID和Label的对应关系表示“created”的ID,并保存在该行中。

在1所在的行中建立一个新的Column,Column名字是一个混合的二进制字段,其中包含了“created”的ID,边的方向(out),vertex-centric indices排序用的sort key(本例为空),相邻的邻接点的ID差值(4-1的前一个邻接点的ID)和这条边自身的独有ID。这个Column的Value则是混合了Label的signature(本例为空)和所有Property(weight=23)的另一个二进制字段。

在4所在的行中建立了另一个相对应的Column,保存了4的入边。

3、存储一个图

Titan是以事务为基础的,因此没一步操作后都会默认commit,所以不用显式的调用语句进行图的存储。

4、根据属性查询节点

假设查询条件是age>10并且name=marko的节点:

g.V.has(“age”, GREATER_THAN, 10).has(“name”, “marko”)

当用户调用hasNext时,titan根据对应的索引找到其rowKey位置,在用户调用next时输出

5、遍历查询

查询上图中,v1出度边为know的邻居中,age>10的节点,查询语句为g.v(1).out('know').has(age,gt,10);

查询过程在另一篇博文中已经阐述,这里要说明的是对于边属性的过滤是如何进行的。

因为一条边可以有多个属性,以key-value串的形式存储在每个column的value中,过滤的时候以解析key-value字符串的形式进行。



2 0
原创粉丝点击