图解Janusgraph系列-图数据底层序列化源码分析(Data Serialize)

大家好,我是洋仔,JanusGraph图解系列文章,实时更新~

图数据库文章总目录:

源码分析相关可查看github(码文不易,求个star~)https://github.com/YYDreamer/janusgraph

下述流程高清大图地址:https://www.processon.com/view/link/5f471b2e7d9c086b9903b629

版本:JanusGraph-0.5.2

转载文章请保留以下声明:

作者:洋仔聊编程

微信公众号:匠心Java

原文地址:https://liyangyang.blog.csdn.net/

正文

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/janusgraph

数据写入的流程源码过多,就不在文章中给出分析了,具体请看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~

图解Janusgraph系列-图数据底层序列化源码分析(Data Serialize)的更多相关文章

  1. Eureka 系列(04)客户端源码分析

    Eureka 系列(04)客户端源码分析 [TOC] 0. Spring Cloud 系列目录 - Eureka 篇 在上一篇 Eureka 系列(01)最简使用姿态 中对 Eureka 的简单用法做 ...

  2. Golang package轻量级KV数据缓存——go-cache源码分析

    作者:Moon-Light-Dream 出处:https://www.cnblogs.com/Moon-Light-Dream/ 转载:欢迎转载,但未经作者同意,必须保留此段声明:必须在文章中给出原文 ...

  3. Spring系列28:@Transactional事务源码分析

    本文内容 @Transactional事务使用 @EnableTransactionManagement 详解 @Transactional事务属性的解析 TransactionInterceptor ...

  4. Django(44)drf序列化源码分析(1)

    序列化与反序列化   一般后端数据返回给前端的数据格式都是json格式,简单易懂,但是我们使用的语言本身并不是json格式,像我们使用的Python如果直接返回给前端,前端用的javascript语言 ...

  5. 大数据之Oozie——源码分析(一)程序入口

    工作中发现在oozie中使用sqoop与在shell中直接调度sqoop性能上有很大的差异.为了更深入的探索其中的缘由,开始了oozie的源码分析之路.今天第一天阅读源码,由于没有编译成功,不能运行测 ...

  6. Java 集合系列(四)—— ListIterator 源码分析

    以脑图的形式来展示Java集合知识,让零碎知识点形成体系 Iterator 对比   Iterator(迭代器)是一种设计模式,是一个对象,用于遍历集合中的所有元素.  Iterator 包含四个方法 ...

  7. Redis学习之底层链表源码分析

    Redis底层链表的源码分析: 一.链表结点的结构(单个结点): // listNode 双端链表节点 typedef struct listNode { // 前置节点 struct listNod ...

  8. vue系列---snabbdom.js使用及源码分析(九)

    一:什么是snabbdom? 在学习Vue或React中,我们了解最多的就是虚拟DOM,虚拟DOM可以看作是一颗模拟了DOM的Javascript树,主要是通过vnode实现一个无状态的组件,当组件状 ...

  9. Spring源码系列(二)--bean组件的源码分析

    简介 spring-bean 组件是 Spring IoC 的核心,我们可以使用它的 beanFactory 来获取所需的对象,对象的实例化.属性装配和初始化等都可以交给 spring 来管理. 本文 ...

随机推荐

  1. day01-系统基础信息模块

    前言:2015年,由于大规模采用云平台虚拟机部署应用,每套应用系统的MySQl.接口机.WEB服务器.文件服务器需要经常进行版本升级.配置更新.安全补丁加固.iptables调整.配置核实,大量的手工 ...

  2. Python一行式代码

    # 简易Web Server,可以直接快速共享文件 python -m http.server # 脚本性能分析 python -m cProfile my_script.py # 列表辗平 impo ...

  3. 如何在Visio 中插入各种数学公式?

    在Visio 2007老版本中,插入公式可以直接在插入图片中选择,但是在后来的Visio2013中却无法直接通过插入图片的方法插入,那么该如何在visio 2013中插入公式呢? 具体的操作步骤如下: ...

  4. MathType中的条件概率的输入

    条件概率公式是高中数学的概率知识中比较常用的一个公式,今天我们来介绍一下在MathType中如何输入条件概率公式. 具体步骤如下: 步骤一 打开专业的公式编辑软件MathType 7,在输入框中输入& ...

  5. guitar pro系列教程(一):Guitar Pro主界面之记谱功能的详细解析【上】

    相信弹吉他的朋友们对guitar pro这款软件并不陌生,也有很多朋友用它来看谱制谱.而GP有很多实用功能,能够使我们看谱更清晰,制谱更便捷,所以让我们一起来看看吧 Guitar Pro对初学作曲,特 ...

  6. 基于Koa2+mongoDB的后端博客框架

    主要框架:koa2全家桶+mongoose+pm2. 在阅读前建议将项目克隆到本地配合食用,否则将看得云里雾里. 项目地址:https://github.com/YogurtQ/koa-server. ...

  7. 无效的HTTP_主机头Invalid HTTP_HOST header: '192.168.56.100:8888'. You may need to add '192.168.56.100' to ALLOWED_HOSTS.

    Invalid HTTP_HOST header: '192.168.56.100:8888'. You may need to add '192.168.56.100' to ALLOWED_HOS ...

  8. Java集合【3】-- iterable接口超级详细解析

    目录 iterable接口 1. 内部定义的方法 1.1 iterator()方法 1.2 forEach()方法 1.3 spliterator()方法 总结 iterable接口 整个接口框架关系 ...

  9. mysql 优化数据类型

    1.更小的通常更好 选择不会超过范围的最小类型 2.简单就好 例如,整型比字符操作代价更低,因为字符集和校对规则(排序规则)使字符比较比整形比较更复杂. 3.尽量避免null 如果查询中包含可为nul ...

  10. Spring Boot 2.4发布了,但Spring Cloud用户不推荐着急升级

    前段时间Spring Boot发布了本年度最后一个重要更新版本:Spring Boot 2.4.0. 最近在社群里也开始有讨论关于Spring Boot 2.4的一些使用问题.我发现有很多Spring ...