图数据库Titan在生产环境中的使用全过程+分析 谁借莪1个温暖的怀抱¢ 2022-07-24 05:01 115阅读 0赞 图数据库Titan在生产环境中的使用全过程+分析 注:本文以Hbase作为backend,并以下图为例 ![\\][20150116095539146.jpg] <喎�"http://www.2cto.com/kf/ware/vc/" target="\_blank" class="keylink">vcD4KPGgxPjChosr9vt3Eo9DNPC9oMT4KPHA+VGl0YW7U2khiYXNl1tC1xLTmtKK94bm5PC9wPgo8dGFibGUgYm9yZGVyPQ=="1" cellspacing="0" cellpadding="0"> 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,代码中是这样的: ![\\][Image 1] ![\\][Image 1] ![\\][Image 1] ![\\][20150116095600152.jpg] # 1、创建一个图 # <pre name="code" class="java">// Gremlin conf = 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的结构。 ![\\][370407.html] 接下来,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字符串的形式进行。 [20150116095539146.jpg]: http://www.2cto.com/uploadfile/Collfiles/20150116/20150116095539146.jpg [Image 1]: [20150116095600152.jpg]: http://www.2cto.com/uploadfile/Collfiles/20150116/20150116095600152.jpg [370407.html]: http://www.2cto.com/database/201501/370407.html
还没有评论,来说两句吧...