用亚马逊海王星探索图形数据库教程

226 阅读15分钟

time lapse photography of blue lights

利用亚马逊海王星探索图形数据库

长期以来,关系型数据库一直是所有数据持久性需求的答案(无论它们是否真的适合该解决方案)。在过去的十年里,不同类型的数据库引擎出现了爆炸性增长。这部分是由数据量和以前没有遇到过的访问模式驱动的。另一个起作用的因素是大型云计算供应商的增长。专业知识的集中化使得这些供应商能够提供专业的数据库技术,而这些技术在以前是中等规模的企业组织所不能企及的。

在这篇文章中,我将看一下这些新的数据库类型之一。图形数据库。作为其中的一部分,我们将看看Apache TinkerPop Gremlin和Amazon Neptune(AWS的图形数据库选项)。

什么是图谱数据库,我为什么要使用它?

在这里没有什么奇怪的,因为它的名字是这样的:图形数据库以一种非常容易建立关系模型的方式来存储数据;它被称为图形。我们谈论的这种图来自数学的一个分支,叫做图论;我们不是在谈论Excel和饼图。在图论中,有两个主要结构:我们有节点和边。节点代表数据实体,边代表它们之间的关系。

我为什么要这样做呢?难道SQL连接还不够好吗?嗯,不是的。对于某些用例,图形数据库胜过关系数据库。这是由于我们的数据实体之间的关系被存储在数据库本身。对于关系型数据库,你要么在运行时使用JOIN命令,要么最终有许多链接表来映射实体之间的关系。

一个典型的例子是社交网络。在下图中,我们有三个人的结点和一个乐队结点。

边缘(friends_with和likes_band)描述了实体之间的关系。以这种方式对这些实体进行映射,可以更直观地推理数据之间的关系。在关系型数据库中进行类似的查询会迅速变得非常昂贵,特别是当你扩展到数百万个节点和边的时候。

我不打算在这里列举用例,而是将其链接到Neo4j(主要的图形数据库供应商之一)提供的这个页面。它提供了一些关于这项技术的合适用例的奇妙想法。

好了,概念性的信息已经足够了,让我们来看看一些例子。我将首先在我的本地机器上运行一些例子,然后我将启动一个Amazon Neptune数据库并在那里复制同样的例子。

Apache TinkerPop Gremlin

这确实是一个东西。Gremlin是由Apache软件基金会提供的一种图形遍历语言。它是与TinkerPop兼容的图数据库一起使用的主要查询语言之一。

这里只是对Apache TinkerPop和Gremlin做一个澄清。TinkerPop可以被认为是图形的JDBC,它是一个API规范,符合TinkerPop标准的数据库必须支持该规范,以便符合TinkerPop标准。Gremlin是用于与该API交互的查询语言之一。

方便的是,Gremlin包提供了一个本地内存服务器,我们可以运行它来玩弄本地数据库。

让我们深入了解一下

我将在这里提出一个简单的例子:一个资产数据库,它对基础设施和应用服务之间的关系进行建模。下面的图片显示了这个基本模型的一个例子。在右边,我们有一些应用服务在AWS账户中运行。这些服务通过代理和VPN与一个内部的客户数据库进行通信。节点之间边缘的箭头显示了依赖关系的方向(即账户服务依赖于代理,而代理依赖于VPN等等)。

Gephi从数据库中动态生成图形

Gremlin控制台的安装

Gremlin的安装非常简单。你只需要安装一个JVM(我试过8和11)。你可以从这里下载并解压Gremlin控制台。一旦你解压后,在你的终端中浏览到bin/目录并运行./gremlin.sh

如果一切顺利的话,你会看到下面的画面。

让我们加载一些数据

我在这个GraphML文件中为我们的简单资产数据库提供了一些数据。GraphML是一种常见的基于XML的数据格式,用于描述图结构。要理解的两个最重要的部分是我们的节点。

和我们的边

在上面我们有两个例子节点(我们的代理和账户服务)。我们把账户服务作为源,把我们的代理作为边的目标。如果你看一下上面链接的GraphML文件,你会看到所有的节点,以及描述它们之间关系的边。

为了加载我的assets.graphml文件,我把它复制到/tmp,然后从Gremlin控制台运行以下命令。

graph = TinkerGraph.open()
graph.io(graphml()).readGraph('/tmp/assets.graphml')
g = graph.traversal()

我们可以在下面的截图中看到结果。7个顶点(节点)和8条边已经被加载到数据库中。

浏览一下这些命令:

  • 第1行打开一个新的TinkerGraph(TinkerPop的内存实现)的内存实例。
  • 第2行读取我们的GraphML文件并将其加载到数据库中。
  • 第3行实例化了一个图形遍历源对象。这将使我们能够对这个图运行遍历查询。遍历查询从一个节点走到另一个节点,与我们的标准相匹配。

我们现在能做什么?

我们已经加载了一些数据。让我们尝试一些简单的查询。

销售服务与什么有关?

很好!所以我们知道销售服务与我们的代理和支付服务有直接的依赖关系。但在查询中究竟发生了什么?Gremlin是一种函数式语言,我们可以从左到右阅读查询中的连锁函数。首先,我们得到一个名为 "销售服务 "的节点。".out() "说要找到所有与我们的节点向外连接的节点。".values('name') "返回这些节点的名称。最后,unfold()以从上到下的列表方式显示结果,而不是以数组方式一个接一个地显示。

哪些节点连接到支付服务?

这是个非常类似的查询。我们用".in() "代替".out()",所以这显示了所有连接到我们的支付服务节点的节点。

从账户服务到客户数据库有哪些路径?

有趣的是。我们有两条路径,我们的账户服务可以采取到客户数据库。要么直接,要么它可以通过 "遗留账户服务 "节点发送查询。从查询的角度来看,发生的情况如下。

  • 获取名为 "账户服务 "的节点
  • repeat(out().simplePath()).until(has('name','Customer Database')) 走过图,从 "账户服务 "开始,直到它到达 "客户数据库"。simplePath()函数意味着遍历器不会重复其在图中的路径(没有循环)。
  • limit(10) 意味着在寻找路径时,遍历器不会走得比10个节点深。在处理密集的复杂图时,这一点很重要,因为在图中遍历太深可能会影响性能。
  • path() 函数将遍历转化为路径,在本例中是通过节点的 "名称 "转化的。

更复杂的东西

对于我们的最后一个例子,让我们做一些相对复杂的事情,但我认为这显示了图数据库在正确使用情况下的力量。假设我们是一个网络管理员,我们想知道所有依赖我们的VPN的下游服务,这样我们就可以向相关的所有者传达计划中的中断。请记住,我们必须找到直接服务,以及所有直接的次级依赖,因为它们都会受到影响。

我们可以看到我们所有的依赖服务。这个查询一开始看起来很吓人,但是SQL的等价物会大得多。让我们看一下这里发生了什么:

  • 我们从 "站点间VPN "节点开始,并将其设置为 "rootNode",这样我们就可以在以后的查询中引用它。
  • 我们现在重复走in()节点的路径,我们递归地这样做,直到我们在该路径上没有更多的传入节点为止
  • where(neq('rootNode')) 意味着我们的输出中不包括我们的根节点
  • dedup() 删除任何重复的节点(即我们可能两次遍历同一个节点,我们不希望在列表中出现这种情况)
  • 最后,我们输出找到的服务的名称

你可能已经注意到了__.in()__.not() 。Gremlin是基于Groovy的,下划线放在这里是为了避免与Groovy的本地关键字冲突。

现在我们看了一下Gremlin语言,让我们快速看看如何用Amazon Neptune服务做类似的事情。

亚马逊Neptune

亚马逊Neptune是一个由亚马逊提供的管理型图形数据库服务。与亚马逊Aurora RDS服务非常相似,你与数据库集群一起工作,这些集群有写入器和读取器来访问数据。更多信息可以在这里的产品页面上找到。对于我们这里的目的来说,最重要的是Neptune支持Gremlin,它还提供了对另一种叫做SPARQL的查询语言的支持,我不会在这里深究。

让我们建立一个简单的集群,看看体验是怎样的。

需要注意的是,Neptune只在VPC内可用,如果你想访问其他AWS服务(例如S3加载数据),你需要设置VPC端点以方便使用。关于这一点的更多信息在这里

文章的这一部分有几个前提条件。1)你需要配置一个VPC,我有一个简单的VPC,配置了一个私有子网,我将在其中启动我的集群;2)你需要在同一个子网中运行一个EC2实例,以访问你的集群(通过Gremlin控制台)。

创建一个Neptune数据库

导航到Neptune控制台,点击 "创建数据库"。

> Create database
Neptune
Create database
Engine options
Engine type
neptune
Version Info
Neptune 1.0.4.1 .RI

注意,我只是把我的数据库引擎留成了默认提供的。现在给你的数据库集群一个唯一的标识符。

Settings
DB cluster identifier Info
Type a name for your DB cluster. The name must be unique cross all DB clusters owned by your AWS account in the current AWS
Region.
shineblog
The DB cluster identifier is case-insensitive, but is stored as all lowercase (as in "mydbcluster"). Constraints: 1 to 60 alphanumeric
characters or hyphens. First character must be a letter. Can't contain two consecutive hyphens. Can't end with a hyphen.

对于我们的目的,使用 "开发和测试 "模板是有意义的。

Templates
Choose a template to meet your use case.
O
Production
Use defaults for high availability and fast, consistent
performance.
O Development and Testing
This instance is intended for development use outside
of a production environment.

由于这只是为了演示的目的,我将使用最小的实例,即t3.medium。

DB instance size
DB instance class
Info
Choose a DB instance class that meets your processing power and memory requirements. The DB instance class options below are
limited to those supported by the engine you selected above.
o
Memory Optimized classes (includes r classes)
O Burstable classes (includes t classes)
db.t3.medium
2 vCPUs 4 GiB RAM EBS: 1500 Mbps
Include previous generation classes

在我们的演示中,不需要在多个可用区进行读复制。

Availability & durability
Multi-AZ deployment
Info
o
Create read replica in different zone
O No

现在我们必须配置我们的网络和安全设置。

Connectivity
Virtual Private Cloud (VPC) Info
VPC that defines the virtual networking environment for this DB cluster.
densikat-testing (vpc-Oe3b871452181fOe9)
Only VPCs with a corresponding DB subnet group are listed.
@ After a database is created, you can't change the VPC selection.
c

注意,你选择的VPC必须是你自己的。

我选择允许控制台为我创建一个新的 "子网组"。这对这个演示并不重要。

我将让控制台创建一个名为 "shineblog-neptune "的安全组--记下这一点以便以后使用。

我保留了8182的默认端口。我们的EC2实例将在这个端口与数据库进行通信。

v Additional connectivity configuration
Subnet group
Info
DB subnet group that defines which subnets and IP ranges the DB instance can use in the VPC you selected.
Create new DB Subnet Group
VPC security group
Choose one or more Neptune security groups to allow access to your database. Ensure that the security group rules allow incoming
traffic from EQ instances and devices outside your VPC. (Security groups are required for publicly accessible databases.)
o
Choose existing
Choose existing VPC security groups
New VPC security group name
shineblog-neptune
Availability zone Info
ap-southeast-2a
Database port Info
O Create new
Create new VPC security group
TCP/IP port the database will use for application connections.
8182

一旦对设置感到满意,继续点击 "创建",开始创建你的集群。

根据下面的截图,当你的数据库创建完成后,它将显示一个 "可用 "的状态。

点击集群,并注意写入者的端点名称,我们将在以后使用它来连接。

安全!

为了使我们的EC2实例能够连接到这个数据库,我们将需要修改数据库安全组。

在下面的截图中,我进入了我们的 "shineblog-neptune "安全组,该组连接到我们的数据库实例。我添加了一个自定义的TCP规则,允许从我们的EC2实例安全组(shine-neptune-testing)的默认端口8182进行通信。

sg-05d3113413be24019 - shineblog-neptune
Details
Inbound rules
Outbound rules
Port range
8182
Tags
Inbound rules
Type
Custom TCP
Protocol
TCP
Source
sg-Obd92ed68672cbb98 (shine-neptune-testing)

从基础设施的角度来看,这应该足以让我们通过EC2实例上的Gremlin控制台进行连接。

连接到你的EC2实例

在这一点上,你会想要连接到你的EC2实例。这不在本文的讨论范围之内,但我假设你有SSH或SSM权限。

你需要在你的实例上安装和设置Gremlin控制台。我建议你去看这个文件,然后按照步骤操作。

那份文件中的几个要点我觉得很混乱或不正确:

  • 在步骤6.c中,他们提到了JRE路径 "jre_path"。在我的实例上,这是/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10-1.amzn2.0.1.x86_64/jre。我通过运行以下命令找到了它 sudo /usr/sbin/alternatives *--config java*
  • keytool命令中提到了Gremlin控制台3.4.8,如果你按照步骤操作,应该是3.4.10。他们还提到了/home/ec2-user;如果你用会话管理器连接,那应该是/home/ssm-user。
  • 第7步提到了 "your-neptune-endpoint"。这将是我提到的你应该注意到的集群端点。

如果你已经做到了这一步

我们现在应该能够从我们的实例连接到我们的Neptune集群。

gremlin> : remote connect tinkerpop. server conf /neptune—remote . yaml
==>Configured shineblog. cluster—cymyOaf2jnb6. neptune . amazonaws.com/172.18.3.83 : 8182
gremlin>

[gremlin> : remote console
scripts will now be sent to Gremlin Server
sole' to return to local mode
— shineb10g.c1uster—cymyOaf2jnb6. ap—southeast—2. neptune . amazonaws.com/172.18.3.83 : 8182
— type
: remote con

看起来不错

在继续前行之前,需要注意的一件事是,在Neptune上运行的Gremlin实现确实有一些不同。在这里的文档中,对这些差异进行了概述。

不幸的是,我们不能通过远程连接从我们现有的GraphML文件中导入。我不得不把GraphML文件中的逻辑和数据转换成一系列我们可以从Gremlin控制台运行的语句。你可以在这里找到这个文件。在该文件中,第一个命令块插入了具有相关数据属性的节点。第二块插入了映射节点之间关系的边。你可以简单地将其复制并粘贴到你的Gremlin控制台,在EC2实例上运行。

其他导入数据的方法

有多种选择可以将数据导入到Neptune。其中一些选项是:

  • 通过Gremlin控制台添加/修改/删除 - 这其实只是为了探索,在现实生活中并没有什么用处
  • 使用Neptune批量加载器从S3获取数据--对批量摄取很有用。需要一个S3 VPC端点和正确的权限
  • 使用AWS数据库迁移服务--对初始匹配摄取和持续复制数据有用
  • 通过编程--例如通过Java Gremlin客户端

在Neptune中查询我们的图

让我们看看与上面相同的查询,但现在从我们的EC2实例远程发送至我们的实时Neptune数据库并在那里执行。

gremlin> g. ) . has( 'name' , ' Sales Service' ) .out() . values( 'name ) un o
Service

gremlin> g.V( ) . has( 'name' , 'Payment Service' ) . ) . values( 'name' ) . unfold( )
Service
Service

总结

唷,我们成功了在继续之前,别忘了终止你的集群。没有免费的层级,而且Neptune也不是特别便宜

所以,总的来说,图式数据库提供了一些强大的方法来在你的数据实体之间建立连接。我真的只是触及了Gremlin可能的表面。如果你对深入了解感兴趣的话,很难超越Kelvin Lawrence的精彩的Gremlin教程。许多关于机场数据的例子真的为我带来了一些闪光点,希望它们对你也有帮助。