关于图数据库:图解Janusgraph系列图数据底层序列化源码分析Data-Serialize

44次阅读

共计 3343 个字符,预计需要花费 9 分钟才能阅读完成。

大家好,我是 洋仔 ,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
  • 生成 vertexedgeproperty 的全局分布式惟一 id
  • 自定义属性验证是否满足唯一性束缚

次要流程如下图(倡议按照源码一块查看,上述 github 地址已给出):

serialize 阶段

次要是对上述 prepare 阶段筹备好的数据进行序列化为二进制数据,为存储二进制数据到 backend storage 做筹备;另外获取本地锁 + 分布式锁数据插入(此处只是将数据插入到 Hbase,插入胜利并不代表获取胜利)

过程中蕴含以下几种作用:

  • 序列化所有 relation 数据并存储,蕴含属性、label edge、normal edge
  • 获取属性对应 index 须要更新的数据,并序列化存储;蕴含 组合索引和 mixed index的解决
  • 获取基于图实例的本地锁
  • 获取了本地锁的前提前,获取 edge lockindex lock 分布式锁(此处的获取锁只是将对应的 KLV 存储到 Hbase 中!存储胜利并不代表获取锁胜利,在 commit 阶段才会去查看是不是获取分布式锁胜利!)

次要流程如下图:

commit 阶段

次要是获取 本地锁 + 分布式锁 胜利后,将对应 序列化 后的数据增加到对应的 backend storage 中;实现图数据插入过程!在此阶段才会对图库中的实在数据开始影响,才会波及到事务的回滚机制;

过程中蕴含以下几种作用:

  • 判断分布式锁的状态,获取胜利则进行数据长久化;不胜利则失败
  • 长久化 relation 数据
  • 长久化 index 数据,蕴含组合索引存储到第三方存储;mixed index存储到第三方索引库中
  • 删除对应的本地锁 和 分布式锁的占用

次要流程如下图:

二:edge 数据写流程

针对于 edge 的写数据流程,整体的流程和 vertex 节点的数据写入雷同,有几点不同,上面一一列出:

1、生成分布式惟一 id 的过程

导入 Edge 数据在生成 edge 的惟一 id 时,partition id的获取不再是 随机获取 ,而是尝试获取边对应的out vertexpartition 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 keysignature 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 中源码剖析正文吧

四:利用

基于数据序列化导入的源码博主将图数据的序列化逻辑抽取进去,生成一个工具包;

次要用于图数据的迁徙和图数据库的初始化,实用于大数据量的导入,次要流程如下:

  1. 生成 schema 到图中
  2. 获取 schema 信息,缓存到内存中
  3. 调用 api 占用对应的 id blocker,用于离线数据的分布式惟一 id 生成
  4. 调用抽取的序列化逻辑序列化节点和边数据
  5. 生成 Hfile
  6. 将 hfile 导入到 Hbase 中

上述流程曾经通过严格的验证并在生产环境中应用,具体之后会再出一篇文章介绍一下具体的设计与流程

五:总结

对于 JanusGraph 图数据的写入,次要分为 3 局部:

  • schema 的创立
  • vertex 节点数据的导入
  • edge 边数据的导入

上述次要剖析了 vertexedge的数据导入,大抵流程类似;也剖析了两局部导入数据的差别;

其中波及的 分布式惟一 id的生成逻辑 和 锁机制获取 的逻辑,请看《图解 Janusgraph 系列 -Lock 锁机制 (本地锁 + 分布式锁) 剖析》和《图解 Janusgraph 系列 - 分布式 id 生成策略剖析》两篇文章!

针对于第三方索引的序列化存储逻辑,逻辑绝对简略,此处没有给出,具体读者能够自主剖析一下源码

码字不易,求个赞和 star~

正文完
 0