大家好,我是洋仔
,JanusGraph图解系列文章,实时更新
~
图数据库文章总目录:
- 整顿所有图相干文章,请移步(超链):图数据库系列-文章总目录
源码剖析相干可查看github(码文不易,求个star~)
: https://github.com/YYDreamer/janusgraph下述流程高清大图地址:https://www.processon.com/view/link/5f471b2e7d9c086b9903b629
版本:JanusGraph-0.5.2
转载文章请保留以下申明:
作者:洋仔聊编程
微信公众号:匠心Java
原文地址:https://segmentfault.com/u/yoylee
注释
JanusGraph的数据导入过程次要分为三阶段:prepare(筹备)、serialize(序列化)、commit(提交);不同阶段有不同的作用,如下:
上面咱们别离从导入vertex
节点和edge
边两局部来剖析写流程
倡议根据源码同步看本文章,便于了解!
一:vertex数据写流程
上面vertex
节点数据的导入,
prepare阶段
次要是根据以后给定的参数,组装出对应的vertex 或者 edge 对象;对象中蕴含对应的id、索引信息、属性信息和锁信息等;
过程中蕴含以下几种作用:
- 默认增加
vertex exist
属性,值为true,标识以后节点是否存在 - 默认增加
label edge
边,标识以后的节点 或者 边是什么label - 生成
vertex
、edge
、property
的全局分布式惟一id - 自定义属性验证是否满足唯一性束缚
次要流程如下图(倡议按照源码一块查看,上述github地址已给出):
serialize阶段
次要是对上述prepare
阶段筹备好的数据进行序列化为二进制数据,为存储二进制数据到backend storage
做筹备; 另外获取本地锁 + 分布式锁数据插入(此处只是将数据插入到Hbase,插入胜利并不代表获取胜利)
过程中蕴含以下几种作用:
- 序列化所有
relation
数据并存储,蕴含属性、label edge、normal edge - 获取属性对应
index
须要更新的数据,并序列化存储; 蕴含组合索引和mixed index
的解决 - 获取基于图实例的本地锁
- 获取了本地锁的前提前,获取
edge lock
和index lock
分布式锁(此处的获取锁只是将对应的KLV存储到Hbase中!存储胜利并不代表获取锁胜利,在commit阶段才会去查看是不是获取分布式锁胜利!)
次要流程如下图:
commit阶段
次要是获取本地锁
+分布式锁
胜利后,将对应序列化
后的数据增加到对应的backend storage
中;实现图数据插入过程! 在此阶段才会对图库中的实在数据开始影响,才会波及到事务的回滚机制;
过程中蕴含以下几种作用:
- 判断分布式锁的状态,获取胜利则进行数据长久化;不胜利则失败
- 长久化
relation
数据 - 长久化
index
数据,蕴含组合索引存储到第三方存储;mixed index
存储到第三方索引库中 - 删除对应的本地锁 和 分布式锁的占用
次要流程如下图:
二:edge数据写流程
针对于edge
的写数据流程,整体的流程和vertex
节点的数据写入雷同,有几点不同,上面一一列出:
1、生成分布式惟一id的过程
导入Edge数据在生成edge的惟一id时,partition id
的获取不再是随机获取
,而是尝试获取边对应的out vertex
的partition id
; id的组成部分也不同,没有idPadding
局部;
具体解释请看:《JanusGraph-分布式id生成策略》文章
2、在edge
的导入中,没有同vertex
数据导入,增加默认的节点是否存在属性
和节点和节点对应label的边
3、获取edge
对应的属性的index update时不同
在导入vertex
数据时,将节点对应的属性作为relation寄存在addRelation中,而后收集所有的属性relation循环获取index uodate;如下伪代码:
for (InternalRelation add : Iterables.filter(addedRelations,filter)) { if (add.isProperty()) mutatedProperties.put(vertex,add); // 此处只操作属性类型的 mutations.put(vertex.longId(), add);}// 此处,收集节点对应属性对应的索引须要更新的数据、减少或删除节点时才有作用; 针对于插入edge的操作,不波及此处for (InternalVertex v : mutatedProperties.keySet()) { indexUpdates.addAll(indexSerializer.getIndexUpdates(v,mutatedProperties.get(v)));}
而在edge
数据导入中,只将edge这条边作为relation插入到addRelation中,所以无奈获取属性relation,转而通过收集过程中,对每个edge对应的所有属性进行别离获取;如下伪代码:
for (InternalRelation add : Iterables.filter(addedRelations,filter)) { if (add.isProperty()) mutatedProperties.put(vertex,add); // 此处只操作属性类型的 mutations.put(vertex.longId(), add); // 获取边蕴含的属性;在节点插入时没有作用,插入边数据时,获取边上的属性对应的索引; 只有edge操作中蕴含边属性,并且蕴含索引! indexUpdates.addAll(indexSerializer.getIndexUpdates(add));}
4、edge
对应的relation数据,也就是以后插入的这个边,须要被序列化两次
一次是源节点+边关系,一次是指标节点+边关系(因为jansugraph是通过edge cut形式存储图数据的)
5、edge
的数据插入过程中,edge的序列化组成部分不同于vertex的序列化组成部分;
不同点请看《Janusgraph-存储构造》文章
6、edge
的数据插入中,edge的property和vertex的property组成不同!
edge
中针对于sort key
和signature key
配置的属性,只将property value
存储在对应地位。其余未被配置的属性值蕴含proeprty key label id + property value
;
不同于vertex数据中的属性组成蕴含:proeprty key label id + property 惟一id +property value
三:源码剖析
源码剖析曾经push到github:https://github.com/YYDreamer/...
数据写入的流程源码过多,就不在文章中给出剖析了,具体请看github中源码剖析正文吧
四:利用
基于数据序列化导入的源码博主将图数据的序列化逻辑抽取进去,生成一个工具包;
次要用于图数据的迁徙和图数据库的初始化,实用于大数据量的导入,次要流程如下:
- 生成schema到图中
- 获取schema信息,缓存到内存中
- 调用api占用对应的id blocker,用于离线数据的分布式惟一id生成
- 调用抽取的序列化逻辑序列化节点和边数据
- 生成Hfile
- 将hfile导入到Hbase中
上述流程曾经通过严格的验证并在生产环境中应用,具体之后会再出一篇文章介绍一下具体的设计与流程
五:总结
对于JanusGraph图数据的写入,次要分为3局部:
- schema的创立
- vertex节点数据的导入
- edge边数据的导入
上述次要剖析了vertex
和edge
的数据导入,大抵流程类似;也剖析了两局部导入数据的差别;
其中波及的分布式惟一id
的生成逻辑 和 锁机制获取
的逻辑,请看《图解Janusgraph系列-Lock锁机制(本地锁+分布式锁)剖析》和《图解Janusgraph系列-分布式id生成策略剖析》两篇文章!
针对于第三方索引的序列化存储逻辑,逻辑绝对简略,此处没有给出,具体读者能够自主剖析一下源码
码字不易,求个赞和star~