【图数据库实战】HugeGraph架构

一、概述

      作为一款通用的图数据库产品,HugeGraph需具备图数据的基本功能,如下图所示。HugeGraph包括三个层次的功能,分别是存储层、计算层和用户接口层。 HugeGraph支持OLTP和OLAP两种图计算类型,其中OLTP实现了Apache TinkerPop3框架,并支持Gremlin查询语言。 OLAP计算是基于SparkGraphX实现。

二、组件

      HugeGraph的主要功能分为HugeCore、ApiServer、HugeGraph-Client、HugeGraph-Loader和HugeGraph-Studio等组件构成,各组件之间的通信关系如下图所示。

  • HugeCore :HugeGraph的核心模块,TinkerPop的接口主要在该模块中实现。HugeCore的功能涵盖包括OLTP和OLAP两个部分。

  • ApiServer :提供RESTFul Api接口,对外提供Graph Api、Schema Api和Gremlin Api等接口服务。

  • HugeGraph-Client:基于Java客户端驱动程序。HugeGraph-Client是Java版本客户端驱动程序,后续可根据需要提供Python、Go、C++等多语言支持。

  • HugeGraph-Loader:数据导入模块。HugeGraph-Loader可以扫描并分析现有数据,自动生成Graph Schema创建语言,通过批量方式快速导入数据。

  • HugeGraph-Studio:基于Web的可视化IDE环境。以Notebook方式记录Gremlin查询,可视化展示Graph的关联关系。HugeGraph-Studio也是本系统推荐的工具。

三、设计理念

        常见的图数据表示模型有两种,分别是RDF(Resource Description Framework)模型和属性图(Property Graph)模型。RDF和Property Graph都是最基础、最有名的图表示模式,都能够表示各种图的实体关系建模。RDF是W3C标准,而Property Graph是工业标准,受到广大图数据库厂商的广泛支持。HugeGraph目前采用Property Graph。

      HugeGraph对应的存储概念模型也是参考Property Graph而设计的,具体示例详见下图:

      在HugeGraph内部,顶点仅存储Id不包含任何属性信息,顶点所有的属性和Label都通过边来存储。如图所示顶点(Id=1)有3个属性分别是name、age和lives,则由三条对应的边指向其具体的属性值,这三条边的Label和顶点属性名相同分别是name、age和lives。

      在HugeGraph内部,顶点与顶点之间的关系也通过边来存储的。但关系的属性并没有像顶点一样分来存储,而是和关系存储在一起。

      顶点属性值通过边指针方式存储时,如果要更新一个顶点特定的属性值直接通过覆盖写入即可,其弊端是冗余存储了VertexId;如果要更新关系的属性需要通过read-and-modify方式,先读取所有属性,修改部分属性,然后再写入存储系统,更新效率较低。从经验来看顶点属性的修改需求较多,而边的属性修改需求较少,例如PageRank和Graph Cluster等计算都需要频繁修改顶点的属性值。

四、 图分区方案

      对于分布式图数据库而言,图的分区存储方式有两种:分别是边分割存储(Edge Cut)和点分割存储(Vertex Cut),如下图所示。使用Edge Cut方式存储图时,任何一个顶点只会出现在一台机器上,而边可能分布在不同机器上,这种存储方式有可能导致边多次存储。使用Vertex Cut方式存储图时,任何一条边只会出现在一台机器上,而每相同的一个点可能分布到不同机器上,这种存储方式可能会导致顶点多次存储。

      采用EdgeCut分区方案可以支持高性能的插入和更新操作,而VertexCut分区方案更适合静态图查询分析,因此EdgeCut适合OLTP图查询,VertexCut更适合OLAP的图查询。HugeGraph目前采用EdgeCut的分区方案。

五、 VertexId 策略

      HugeGraph的Vertex支持三种ID策略,在同一个图数据库中不同的VertexLabel可以使用不同的Id策略,目前HugeGraph支持的Id策略分别是:

  • 自动生成(AUTOMATIC):使用Snowflake算法自动生成全局唯一Id,Long类型;

  • 主键(PRIMARY_KEY):通过VertexLabel+PrimaryKeyValues生成Id,String类型;

  • 自定义(CUSTOMIZE_STRING|CUSTOMIZE_NUMBER):用户自定义Id,分为String和Long类型两种,需自己保证Id的唯一性;

      默认的Id策略是AUTOMATIC,如果用户调用primaryKeys()方法并设置了正确的PrimaryKeys,则自动启用PRIMARY_KEY策略。启用PRIMARY_KEY策略后HugeGraph能根据PrimaryKeys实现数据去重。

     1.AUTOMATIC ID策略

schema.vertexLabel("person").useAutomaticId().properties("name", "age", "city").create();graph.addVertex(T.label, "person","name", "marko", "age", 18, "city", "Beijing");

     2.PRIMARY_KEY ID策略

schema.vertexLabel("person").usePrimaryKeyId().properties("name", "age", "city").primaryKeys("name", "age").create();graph.addVertex(T.label, "person","name", "marko", "age", 18, "city", "Beijing");

3.CUSTOMIZE_STRING ID策略

schema.vertexLabel("person").useCustomizeStringId().properties("name", "age", "city").create();graph.addVertex(T.label, "person", T.id, "123456", "name", "marko","age", 18, "city", "Beijing");

4.CUSTOMIZE_NUMBER ID策略

schema.vertexLabel("person").useCustomizeNumberId().properties("name", "age", "city").create();graph.addVertex(T.label, "person", T.id, 123456, "name", "marko","age", 18, "city", "Beijing");

如果用户需要Vertex去重,有三种方案分别是:

  1. 采用PRIMARY_KEY策略,自动覆盖,适合大数据量批量插入,用户无法知道是否发生了覆盖行为

  2. 采用AUTOMATIC策略,read-and-modify,适合小数据量插入,用户可以明确知道是否发生覆盖

  3. 采用CUSTOMIZE_STRING或CUSTOMIZE_NUMBER策略,用户自己保证唯一

六、 EdgeId 策略

      HugeGraph的EdgeId是由srcVertexId+edgeLabel+sortKey+tgtVertexId四部分组合而成。其中sortKey是HugeGraph的一个重要概念。在Edge中加入sortKey作为Edge的唯一标识的原因有两个:

  1. 如果两个顶点之间存在多条相同Label的边可通过sortKey来区分

  2. 对于SuperNode的节点,可以通过sortKey来排序截断。

      由于EdgeId是由srcVertexId+edgeLabel+sortKey+tgtVertexId四部分组合,多次插入相同的Edge时HugeGraph会自动覆盖以实现去重。需要注意的是如果批量插入模式下Edge的属性也将会覆盖。

      另外由于HugeGraph的EdgeId采用自动去重策略,对于self-loop(一个顶点存在一条指向自身的边)的情况下HugeGraph认为仅有一条边,对于采用AUTOMATIC策略的图数据库(例如TitianDB)则会认为该图存在两条边。

HugeGraph的边仅支持有向边,无向边可以创建Out和In两条边来实现。

七 HugeGraph 事务处理

7.1 TinkerPop事务概述

      TinkerPop transaction事务是指对数据库执行操作的工作单元,一个事务内的一组操作要么执行成功,要么全部失败。详细介绍请参考TinkerPop官方文档:http://tinkerpop.apache.org/docs/current/reference/#transactions

7.2 TinkerPop事务操作接口
  • open 打开事务

  • commit 提交事务

  • rollback 回滚事务

  • close 关闭事务

7.3 TinkerPop事务规范
  • 事务必须显式提交后才可生效(未提交时修改操作只有本事务内查询可看到)

  • 事务必须打开之后才可提交或回滚

  • 如果事务设置自动打开则无需显式打开(默认方式),如果设置手动打开则必须显式打开

  • 可设置事务关闭时:自动提交、自动回滚(默认方式)、手动(禁止显式关闭)等3种模式

  • 事务在提交或回滚后必须是关闭状态

  • 事务在查询后必须是打开状态

  • 事务(非threaded tx)必须线程隔离,多线程操作同一事务互不影响

更多事务规范用例见:Transaction Test

7.4 HugeGraph事务实现
  • 一个事务中所有的操作要么成功要么失败

  • 一个事务只能读取到另外一个事务已提交的内容(Read committed)

  • 所有未提交的操作均能在本事务中查询出来,包括:

    • 增加顶点能够查询出该顶点

    • 删除顶点能够过滤掉该顶点

    • 删除顶点能够过滤掉该顶点相关边

    • 增加边能够查询出该边

    • 删除边能够过滤掉该边

    • 增加/修改(顶点、边)属性能够在查询时生效

    • 删除(顶点、边)属性能够在查询时生效

  • 所有未提交的操作在事务回滚后均失效,包括:

    • 顶点、边的增加、删除

    • 属性的增加/修改、删除

      示例:一个事务无法读取另一个事务未提交的内容

1. static void testUncommittedTx(final HugeGraph graph) throws InterruptedException {2. final CountDownLatch latchUncommit = new CountDownLatch(1);3. final CountDownLatch latchRollback = new CountDownLatch(1);4. Thread thread = new Thread(() -> {5. // this is a new transaction in the new thread6. graph.tx().open();7. System.out.println("current transaction operations");8. Vertex james = graph.addVertex(T.label, "author",9. "id", 1, "name", "James Gosling",10. "age", 62, "lived", "Canadian");11. Vertex java = graph.addVertex(T.label, "language", "name", "java",12. "versions", Arrays.asList(6, 7, 8));13. james.addEdge("created", java);14. // we can query the uncommitted records in the current transaction15. System.out.println("current transaction assert");16. assert graph.vertices().hasNext() == true;17. assert graph.edges().hasNext() == true;18. latchUncommit.countDown();19. try {20. latchRollback.await();21. } catch (InterruptedException e) {22. throw new RuntimeException(e);23. }24. System.out.println("current transaction rollback");25. graph.tx().rollback();26. });27. thread.start();28. // query none result in other transaction when not commit()29. latchUncommit.await();30. System.out.println("other transaction assert for uncommitted");31. assert !graph.vertices().hasNext();32. assert !graph.edges().hasNext();33. latchRollback.countDown();34. thread.join();35. // query none result in other transaction after rollback()36. System.out.println("other transaction assert for rollback");37. assert !graph.vertices().hasNext();38. assert !graph.edges().hasNext();39. }

   事务实现原理

  • 服务端内部通过将事务与线程绑定实现隔离(ThreadLocal)

  • 本事务未提交的内容按照时间顺序覆盖老数据以供本事务查询最新版本数据

  • 底层依赖后端数据库保证事务原子性操作(如Cassandra/RocksDB的batch接口均保证原子性)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/188278.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【源码系列】短剧系统开发国际版短剧系统软件平台介绍

系统介绍 短剧是一种快节奏、紧凑、有趣的戏剧形式,通过短时间的精彩表演,向观众传递故事的情感和思考。它以其独特的形式和魅力,吸引着观众的关注,成为了当代戏剧娱乐中不可或缺的一部分。短剧每一集都是一个小故事,…

1-2 暴力破解-模拟

模拟:根据题目要求编写代码 可分为:图形排版(根据某种规则输出特定图形)、日期问题、其他模拟 一.图形排版 1.输出梯形(清华大学) 法一:等差数列 分析:每行的星号个数为等差数列2n2…

数据结构与算法之美学习笔记:20 | 散列表(下):为什么散列表和链表经常会一起使用?

目录 前言LRU 缓存淘汰算法Redis 有序集合Java LinkedHashMap解答开篇 & 内容小结 前言 本节课程思维导图: 今天,我们就来看看,在这几个问题中,散列表和链表都是如何组合起来使用的,以及为什么散列表和链表会经常…

C++类中public 和 protected 和 private访问权限 struct和class的区别 类成员设置为私有自己控制权限

public 和 protected 和 private访问权限 public 公共权限 类内可以访问 类外可以访问 protected 保护权限 类内可以访问 类外不可以访问 儿子可以访问父亲中的保护内容如父亲的车 private 私有权限 类内可以访问 类外不可以访问 儿子不可以访问父亲的私有权限内容如不想…

Linux 无名管道实现文件复制

无名管道 通过一个管道(假象)进行传输数据,但是这个管道的传输方式是单工(半双工)的,就是这个管道允许进行发送和接受数据,不过不能同时进行。 创建无名管道 这里用到一个pipe(&…

基于黄金正弦算法优化概率神经网络PNN的分类预测 - 附代码

基于黄金正弦算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于黄金正弦算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于黄金正弦优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神…

Java内存区域速览

文章目录 JVM的组成加载字节码流程 运行时数据区-总览1. 程序计数器2. 虚拟机栈栈帧栈的运行原理 3. 本地方法栈4. 堆内存(Java Heap虚拟机对堆 的划分1. 年轻代(Young Generation):2. 老年代(Old Generation)&#xf…

基于黏菌算法优化概率神经网络PNN的分类预测 - 附代码

基于黏菌算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于黏菌算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于黏菌优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神经网络的光滑…

为什么Go是后端开发的未来

近年来,Go 编程语言的流行度迅速增加。Go 最初由 Google 开发,迅速成为后端开发中最受欢迎的语言之一,特别是在分布式系统和微服务的开发中。本文将讨论为什么 Go 是后端开发的未来。 Go 简介 Go,又称为 Golang,是由…

基于springboot实现私人健身与教练预约管理系统项目【项目源码+论文说明】

基于springboot实现私人健身与教练预约管理系统演示 摘要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应…

端口映射软件

今天给大家介绍一个自己制作的工具,本工具可以把本地自己的项目映射到外网可以访问,自己有域名可以使用自己的,没有可以用软件自带的三级域名! Token获取 地址:传送 打开上面网址注册账号,然后点击验证,复制里面的值即可。 软件…

JSplacement丨随机生成置换贴图

界面很简单,虽然是英文,但基本也能看懂,参数调一调,随机生成不重复的8K高清图片。 这种图片可能对普通人感觉很奇怪,有什么用呢?会C4D建模渲染的同学应该会明白,特别是建一些科技类的场景背景&a…