JanusGraph的优势所在

简介

JanusGraph的优势

JanusGraph在设计上针对图操作进行了优化,以便进行大规模的图运算,它的计算和存储能力远超单机图数据库所能提供的。实时图遍历和图分析是JanusGraph最基本的能力。本章将会探讨JanusGraph的各种具体优势以及它潜在的,可支持的持久化方案。

基本优势

  • 支持超大图。 JanusGraph图规模依赖于集群中机器的数量。
  • 支持超大规模并发事务和可操作图运算。JanusGraph事务处理能力依赖于集群中的机器数量,同时JanusGraph可以支撑在巨型图上的复杂遍历查询毫秒级响应。
  • 通过Hadoop架构,支持全图分析或者批量图处理。
  • 支持对超大图的定点和边的基于地理范围查询,数字范围查询,支持全文检索。
  • 支持常见属性图数据模型(property graph data model) 基于开源图计算框架 Apache TinkerPop.
  • 支持图查询语言 Gremlin.
  • 大量图级配置提供了效果微调能力
  • 以顶点为中心的索引提供顶点级查询以缓解臭名昭著的超级节点问题 super node problem.
  • 优化磁盘表示以提供高效存储和快速访问。
  • 开源符合规范 Apache 2 license.

JanusGraph 联合 Apache Cassandra

image.png
  • Continuously available 没有单点故障问题,保障持续可用性。

  • 因为不是主从结构,不存在图的读写瓶颈问题。

  • Elastic scalability 弹性可扩展允许随时添加或者删减机器。

  • 缓存层确保经常被访问的数据存储在内存中。

  • 随着集群中机器的增加,缓存层的大小也会增加。

  • 整合 Apache Hadoop.

  • 开源符合规范 Apache 2 license.

JanusGraph 联合 HBase

image
  • 高度整合 Apache Hadoop 生态系统.
  • 符合强一致性原则 strong consistency.
  • 添加机器符合线性扩展原则。
  • Strictly consistent 绝对一致性读取和写入。
  • 有便捷的基础类库支持使用Hbase表的Hadoop MapReduce jobs
  • 支持指标(是指的监控吗?)导出通过 JMX.
  • 开源符合规范 Apache 2 license.

JanusGraph 与 the CAP 原理

不管你做的多完美,你的系统仍然会面临众多的错误情况。因此你必须在降低产量(减少响应请求)和减少收成(基于部分数据给出结果)之间做出选择。当然选择应该取决于业务需求。

Coda Hale

在使用数据库的时候, 需要考虑CAP原理 CAP theorem (C=一致性(Consistency), A=可用性(Availability), P=可靠性(Partitionability)). JanusGraph支持三种数据库后端系统: Apache Cassandra, Apache HBase, and Oracle Berkeley DB Java Edition. 需要注意的是 BerkeleyDB JE 是一种非分布式数据库,所以一般是用于测试和探索。

HBase gives preference to consistency at the expense of yield, i.e. the probability of completing a request. Cassandra gives preference to availability at the expense of harvest, i.e. the completeness of the answer to the query (data available/complete data).

开动

The examples in this section make extensive use of a toy graph distributed with JanusGraph called The Graph of the Gods. This graph is diagrammed below. The abstract data model is known as a Property Graph Model and this particular instance describes the relationships between the beings and places of the Roman pantheon. Moreover, special text and symbol modifiers in the diagram (e.g. bold, underline, etc.) denote different schematics/typings in the graph.

image.png

符号 含义
粗体字 图索引标记
带星号的粗体字 有唯一值的图索引标记
带下划线的字 以顶点为中心的索引标记
带空箭头的边 功能性的?/唯一的边 (不重复)
带尾缘的边 单向边 (只能向一个方向移动)

下载 JanusGraph 并运行 Gremlin 控制台

JanusGraph 可以在下面的地址下载到: Releases . 下载完成后解压缩,就可以打开 Gremlin 控制台了. Gremlin 控制台是一个 REPL (i.e. 互动shell) 它与JanusGraph一起发行,与标准Gremlin Console的区别仅在于,JanusGraph是一个预安装和预加载的软件包。 或者,用户可以从项目仓库中下载JanusGraph软件包,并在现有的Gremlin Console中安装并激活JanusGraph。 在下面的示例中,使用了“janusgraph.zip”,但是请确保解压缩下载的zip文件。

重要提示
JanusGraph 需要 Java 8 (Standard Edition). 推荐使用Oracle Java 8. JanusGraph的 shell 脚本需要配置环境变量,你需要把 $JAVA_HOME 环境变量指向 JRE or JDK 的安装路径.

$ unzip janusgraph-0.4.0-hadoop2.zip
Archive:  janusgraph-0.4.0-hadoop2.zip
creating: janusgraph-0.4.0-hadoop2/
...
$ cd janusgraph-0.4.0-hadoop2
$ bin/gremlin.sh

         \,,,/
         (o o)
-----oOOo-(3)-oOOo-----
09:12:24 INFO  org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph  - HADOOP_GREMLIN_LIBS is set to: /usr/local/janusgraph/lib
plugin activated: tinkerpop.hadoop
plugin activated: janusgraph.imports
gremlin>

The Gremlin 控制台使用 Apache Groovy 来解析命令. Groovy是Java的超集,具有各种速记符号,使交互式编程更容易。 同理 Gremlin-Groovy 是 Groovy 的超集,具有各种速记符号,使图遍历更加容易。下面的基本示例演示了如何处理 numbers, strings 和 maps. 本章的剩余部分讲讨论关于图处理的特定操作。

gremlin> 100-10
==>90
gremlin> "JanusGraph:" + " The Rise of Big Graph Data"
==>JanusGraph: The Rise of Big Graph Data
gremlin> [name:'aurelius', vocation:['philosopher', 'emperor']]
==>name=aurelius
==>vocation=[philosopher, emperor]

Tip
参考 Apache TinkerPop, SQL2Gremlin, and Gremlin Recipes 获取更多使用 Gremlin的信息.

加载众神图导入 JanusGraph

本示例将会加载一个众神之图的数据集进入 JanusGraph 并生成一个图实例。 JanusGraphFactory 提供了一系列静态的 open 方法, 每个‘open’方法都以配置作为参数并返回一个图实例。本教程使用一种配置调用其中一个‘open’方法,该示例使用BerkeleyDB 做存储,使用 Elasticsearch做索引,使用助手类来加载众神之图. 本节忽略了配置细节,关于更多关于存储,索引和配置的详细信息可以参见其他章节 Storage Backends, Index Backends, and Configuration Reference.

gremlin> graph = JanusGraphFactory.open('conf/janusgraph-berkeleyje-es.properties')
==>standardjanusgraph[berkeleyje:../db/berkeley]
gremlin> GraphOfTheGodsFactory.load(graph)
==>null
gremlin> g = graph.traversal()
==>graphtraversalsource[standardjanusgraph[berkeleyje:../db/berkeley], standard]

The JanusGraphFactory.open() 和 GraphOfTheGodsFactory.load() 方法在返回新图之前做了如下步骤:

  1. 在图上创建全局和顶点中心索引的集合。
  2. 将所有顶点及其属性添加到图中。
  3. 将所有边及其属性添加到图中。

请查看 GraphOfTheGodsFactory source code 了解更多细节.

对于使用 JanusGraph/Cassandra (or JanusGraph/HBase), 确保使用配置文件conf/janusgraph-cql-es.properties (or conf/janusgraph-hbase-es.properties) 和 GraphOfTheGodsFactory.load().

gremlin> graph = JanusGraphFactory.open('conf/janusgraph-cql-es.properties')
==>standardjanusgraph[cql:[127.0.0.1]]
gremlin> GraphOfTheGodsFactory.load(graph)
==>null
gremlin> g = graph.traversal()
==>graphtraversalsource[standardjanusgraph[cql:[127.0.0.1]], standard]

你也可能会用到 conf/janusgraph-cql.properties, conf/janusgraph-berkeleyje.properties, or conf/janusgraph-hbase.properties 配置文件来打开一个不带有索引后端配置(without an indexing backend configured)的图。 在这样的情况下,你需要使用 GraphOfTheGodsFactory.loadWithoutMixedIndex() 方法来加载众神的图,这样它就不会尝试利用索引后端。

==>standardjanusgraph[cql:[127.0.0.1]]
gremlin> GraphOfTheGodsFactory.loadWithoutMixedIndex(graph, true)
==>null
gremlin> g = graph.traversal()
==>graphtraversalsource[standardjanusgraph[cql:[127.0.0.1]], standard]

全局图指数
The typical pattern for accessing data in a graph database is to first locate the entry point into the graph using a graph index.在图数据库中访问数据的典型模式是首先使用图索引定位入口在图中的位置。该入口点是一个元素(或一组元素),即顶点或边。 Gremlin路径描述描述了从入口元素开始,如何通过显式图结构遍历图中的其他元素。

假定name字段为唯一索引,Saturn可以被访问。 然后可以查看Saturn节点的属性图(即Saturn的键/值对)。 如图所示,Saturn顶点的name字段为“Saturn”,年龄为10000,类型为“Titan”。通过遍历我们可以找到Saturn的孙子节点,该查询可以表示为:“谁是Saturn的孙子?”(“father”的反向是“儿子”)。我们查询的结果就是Hercules。

gremlin> saturn = g.V().has('name', 'saturn').next()
==>v[256]
gremlin> g.V(saturn).valueMap()
==>[name:[saturn], age:[10000]]
gremlin> g.V(saturn).in('father').in('father').values('name')
==>hercules

图索引中也包含place属性. place 是一种边属性。因此,JanusGraph也可以在图索引中为边建立索引。因此要在 The Graph of the Gods 查询所有发生在 Athens (经度:37.97 and 纬度:23.72)周围五十公里以内的事件也是可以的。 然后把涉及这些事件的顶点的信息都给出来。

gremlin> g.E().has('place', geoWithin(Geoshape.circle(37.97, 23.72, 50)))
==>e[a9x-co8-9hx-39s][16424-battled->4240]
==>e[9vp-co8-9hx-9ns][16424-battled->12520]
gremlin> g.E().has('place', geoWithin(Geoshape.circle(37.97, 23.72, 50))).as('source').inV().as('god2').select('source').outV().as('god1').select('god1', 'god2').by('name')
==>[god1:hercules, god2:hydra]
==>[god1:hercules, god2:nemean]

图索引是JanusGraph中索引结构的一种类型。 JanusGraph自动选择图形索引来按照要求给出所有满足一个或多个约束(例如,具有或间隔)的所有顶点(g.V)或所有边(g.E)的索引。 JanusGraph中索引的第二个优势是以顶点为中心的索引。 以顶点为中心的索引可加快图形内部的遍历速度。 顶点中心索引将在稍后介绍。

Graph Traversal Examples

Hercules, 是 Jupiter 出轨和 Alcmene生的儿子, 他生来就是大力神. Hercules 是一个半神 Demigod 因为他爸是神但他妈是人. Juno, Jupiter的老婆, 对于Jupiter的出轨极为愤怒. 为了报复,她使用神力让Hercules精神错乱,杀死了自己的孩子和妻子,并且还弄瞎了自己。为了赎罪,Oracle of Delphi 下令让 Hercules 服侍 Eurystheus. Eurystheus 命令Hercules做 12 项工作.

在前面的章节,我们已经知道 Saturn’s 孙子是 Hercules. 可以说这里运用了 loop. 在本质上, Hercules是距离Saturn两步远的定点,沿着 in('father') 这条线.

gremlin> hercules = g.V(saturn).repeat(__.in('father')).times(2).next()
==>v[1536]

Hercules是一个半神. 为了证明Hercules 是一般人一半神,那么他父母的血统都应该被验证。因此,从Hercules节点出发访问他的母亲和父亲节点都应该是可以的。最终,我们可以判定他们的类型“神”和“人”。

gremlin> g.V(hercules).out('father', 'mother')
==>v[1024]
==>v[1792]
gremlin> g.V(hercules).out('father', 'mother').values('name')
==>jupiter
==>alcmene
gremlin> g.V(hercules).out('father', 'mother').label()
==>god
==>human
gremlin> hercules.label()
==>demigod

迄今为止,例子都是围绕罗马万神殿中各个角色的遗传体系的。这个众神的属性图模型 Property Graph Model 足够充分的表达多种事物的类型和关系。同样的,The Graph of the Gods 这个图也能标记Hercules的各种英勇事迹——他最著名的十二项工作。在前面的章节,我们可以知道Hercules参与了Athens附近的两场战斗。同样的,通过遍历从Hercules顶点出发的battled边属性也能找到这些事件。

gremlin> g.V(hercules).out('battled')
==>v[2304]
==>v[2560]
==>v[2816]
gremlin> g.V(hercules).out('battled').valueMap()
==>[name:[nemean]]
==>[name:[hydra]]
==>[name:[cerberus]]
gremlin> g.V(hercules).outE('battled').has('time', gt(1)).inV().values('name')
==>cerberus
==>hydra

以顶点为中心的索引会为一个顶点存在战争的边的时间属性建立索引。通过限制/过滤时间来检索Hercules的战争边事件要比对所有边进行线性扫描和过滤的速度快(通常时间复杂度是O(log n),其中n是事件边的数目)。JanusGraph可以使用以顶点为中心的索引,这很有效而且很高端。 下面我们用一个 Gremlin 的 toString() 表达式来显示了拆解的步骤 。

gremlin> g.V(hercules).outE('battled').has('time', gt(1)).inV().values('name').toString()
==>[GraphStep([v[24744]],vertex), VertexStep(OUT,[battled],edge), HasStep([time.gt(1)]), EdgeVertexStep(IN), PropertiesStep([name],value)]

一个更复杂的图遍历的栗子🌰

Pluto住在塔尔塔洛斯(地狱)的深处。由于Hercules抽了他的宠物Cerberus,他和Hercules的关系变得紧张。但是Hercules是他的侄子,所以,他应该如何让Hercules为傲慢无礼付出代价呢?

下面的Gremlin语句为遍历“众神之图”提供了更多示例。在每句重要的命令前面,都用 // 作为注释进行了解释。

COHABITERS OF TARTARUS 塔尔塔洛斯的居民

gremlin> pluto = g.V().has('name', 'pluto').next()
==>v[2048]
gremlin> // who are pluto's cohabitants? 谁和pluto住在一起?
gremlin> g.V(pluto).out('lives').in('lives').values('name')
==>pluto
==>cerberus
gremlin> // pluto can't be his own cohabitant pluto不能是他自己的同居人
gremlin> g.V(pluto).out('lives').in('lives').where(is(neq(pluto))).values('name')
==>cerberus
gremlin> g.V(pluto).as('x').out('lives').in('lives').where(neq('x')).values('name')
==>cerberus

PLUTO’S BROTHERS ploto的兄弟

gremlin> // where do pluto's brothers live? pluto的兄弟住在哪
gremlin> g.V(pluto).out('brother').out('lives').values('name')
==>sky
==>sea
gremlin> // which brother lives in which place? 哪个兄弟住在哪个地方
gremlin> g.V(pluto).out('brother').as('god').out('lives').as('place').select('god', 'place')
==>[god:v[1024], place:v[512]]
==>[god:v[1280], place:v[768]]
gremlin> // what is the name of the brother and the name of the place? 兄弟的名称和住所的名称
gremlin> g.V(pluto).out('brother').as('god').out('lives').as('place').select('god', 'place').by('name')
==>[god:jupiter, place:sky]
==>[god:neptune, place:sea]

最后,Pluto因为不关心死亡所以住在塔尔塔洛斯。他的兄弟们,也处于自己的热爱而选择了自己所居住的地方。

gremlin> g.V(pluto).outE('lives').values('reason')
==>no fear of death
gremlin> g.E().has('reason', textContains('loves'))
==>e[6xs-sg-m51-e8][1024-lives->512]
==>e[70g-zk-m51-lc][1280-lives->768]
gremlin> g.E().has('reason', textContains('loves')).as('source').values('reason').as('reason').select('source').outV().values('name').as('god').select('source').inV().values('name').as('thing').select('god', 'reason', 'thing')
==>[god:neptune, reason:loves waves, thing:sea]
==>[god:jupiter, reason:loves fresh breezes, thing:sky]

Architectural Overview 架构概述

JanusGraph是一个图形数据库引擎。 JanusGraph本身专注于紧凑的图形序列化,丰富的图形数据建模和有效的查询执行。 此外,JanusGraph利用Hadoop进行图分析和批量图处理。 JanusGraph为数据持久性,数据索引和客户端访问实现了强大的模块化接口。 JanusGraph的模块化的体系结构使其可以与多种存储,索引和客户端技术进行交互。 另外,扩展的JanusGraph支持新的也很方便。

在JanusGraph和磁盘之间放置一个或多个存储和索引适配器。 JanusGraph是以下适配器的标准配置,但JanusGraph的模块化体系结构支持第三方适配器。

广义上讲,应用程序可以通过两种方式与JanusGraph交互:

  • 将JanusGraph嵌入应用程序中执行 Gremlin 查询直接针对graph,使用相同的JVM。 查询执行,JanusGraph的缓存和事务处理都在与应用程序相同的JVM中进行,而从存储后端检索的数据可能是本地的或远程的。

  • 通过将Gremlin查询提交到服务器,与本地或远程JanusGraph实例进行交互。JanusGraph支持 Apache TinkerPop 堆栈的Gremlin服务器组件。

    image.png

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容