什么是 Azure Cosmos DB for Apache Gremlin?

适用对象: Gremlin

Azure Cosmos DB 是一种用于新式应用开发的完全托管的 NoSQL 数据库和关系数据库。

Azure Cosmos DB for Apache Gremlin 是一种图形数据库服务,可用于存储具有数十亿个顶点和边缘的大量图形。 可在毫秒级延迟的情况下查询图形,并轻松改进图结构。 API for Gremlin 基于 Apache TinkerPop,后者是一种使用 Gremlin 查询语言的图形计算框架。

重要

Azure Cosmos DB Graph 引擎紧密遵循 Apache TinkerPop 规范。 但是,特定于 Azure Cosmos DB 的实现详细信息有一些差异。 Apache TinkerPop 支持的某些功能在 Azure Cosmos DB 中不可用,若要了解有关不支持的功能的详细信息,请参阅 Apache TinkerPop 的兼容性文章。

API for Gremlin 将图形数据库算法的强大功能与高度可缩放的托管基础结构相结合。 此方法针对灵活约束和关系约束相关的常见数据问题提供独特且灵活的解决方案。

API for Gremlin 好处

在 Azure Cosmos DB 上构建时,API for Gremlin 具有以下额外优点:

  • 可弹性缩放的吞吐量和存储:现实世界中的图形需要扩展到超越单个服务器的容量。 Azure Cosmos DB 支持横向可缩放的图形数据库,就存储和预配吞吐量而言,这些数据库的大小没有限制。 随着图形数据库规模的增长,数据将使用图形分区自动分发。

  • 多区域复制:Azure Cosmos DB 可以自动将图形数据复制到中国任何 Azure 区域。 多区域复制简化了需要多区域访问数据的应用程序的开发过程。 除了最大程度地减少中国的任何地区的读写延迟外,Azure Cosmos DB 还提供服务托管的区域故障转移机制。 此机制可确保在某个区域服务中断这一罕见情况下应用程序仍保持有连续性。

  • 使用最广泛采用的图形查询标准进行快速查询和遍历:存储异类顶点和边缘,并通过常用的 Gremlin 语法对其进行查询。 Gremlin 是一种命令式函数查询语言,提供了丰富的接口来实现常见的图形算法。 API for Gremlin 支持丰富的实时查询和遍历,而无需指定架构提示、二级索引或视图。 有关详细信息,请参阅使用 Gremlin 查询图形

  • 完全托管的图形数据库:通过 Azure Cosmos DB 无需管理数据库和计算机资源。 大多数现有的图形数据库平台受其基础结构的限制,并且通常需要进行高度维护才能确保其运营。 作为一种完全托管的服务,Cosmos DB 无需管理虚拟机、更新运行时软件、管理分片或复制或者处理复杂的数据层升级。 每个图形会自动备份,以防受到区域故障的影响。 此管理使得开发人员能够专注于提供应用程序价值,而不是专注于操作和管理其图形数据库。

  • 自动编制索引:默认情况下,API for Gremlin 自动为图形中的节点(也称为顶点)和边缘包含的所有属性编制索引,无需任何架构或创建二级索引。 有关详细信息,请参阅在 Azure Cosmos DB 中编制索引

  • 与 Apache TinkerPop 的兼容性:API for Gremlin 支持开源 Apache TinkerPop 标准。 Apache TinkerPop 标准拥有丰富的应用程序和库生态系统,它们可以轻松地与该 API 集成。

  • 可优化一致性级别:Azure Cosmos DB 提供了五个定义明确的一致性级别,以实现应用程序的一致性和性能之间的适当平衡。 对于查询和读取操作,Azure Cosmos DB 提供五种不同的一致性级别:强、有限过时、会话、一致前缀和最终。 通过这些细化的妥善定义的一致性级别,可以在一致性、可用性与延迟之间实现合理的平衡。 有关详细信息,请参阅 Azure Cosmos DB 中的可优化数据一致性级别

API for Gremlin 的常见方案

以下是 Azure Cosmos DB 的图形支持可能有用的一些场景:

  • 社交网络/客户 365:通过合并有关客户及其与其他人的互动的数据,可以开发个性化的体验、预测客户行为,或者将某些人员与其他具有类似兴趣的人员相连接。 使用 Azure Cosmos DB 可以管理社交网络以及跟踪客户的喜好与数据。

  • 推荐引擎:此方案通常用于零售行业。 通过合并有关产品、用户和用户互动(例如购买、浏览某件商品或者为商品评分)的信息,可以生成自定义的推荐内容。 Azure Cosmos DB 的低延迟、弹性缩放和原生图形支持是这些场景的理想选择。

  • 地理空间:电信、物流和旅行规划行业中的许多应用程序需要在某个区域中查找兴趣点,或者查找两个地点之间最短/最佳的路线。 Azure Cosmos DB 天生就很适合解决这些问题。

  • 物联网:当 IoT 设备之间的网络和连接建模为图形时,可以更好地理解设备和资产的状态。 还可以了解网络一个部分的更改可能对另一个部分造成的影响。

图形数据库简介

现实世界中的数据存在必然的联系。 传统数据建模侧重于单独定义实体并在运行时计算它们之间的关系。 虽然这种模型有其自身的优点,但高度连接的数据在其约束下可能难以进行管理。

而图形数据库方法依赖于存储层中的持久关系,这使得图形检索操作非常高效。 API for Gremlin 支持属性图形模型

属性图形对象

属性图形是由顶点边缘组成的结构。 两个对象都可以作为属性包含任意数量的键值对。

  • 顶点/节点:顶点表示人员、地点或事件等离散实体。

  • 边缘/关系:边缘表示顶点之间的关系。 例如,一个人可能认识其他人、涉及到某个事件或最近处于某个位置。

  • 属性:属性表示有关顶点和边缘的信息(或元数据)。 顶点或边缘中可以包含任意数量的属性,并且这些属性可用于描述和筛选查询中的对象。 属性示例包括具有姓名和年龄的顶点,或具有时间戳和/或体重的边缘。

  • 标签 - 标签是顶点或边缘的名称或标识符。 标签可以对多个顶点或边缘进行分组,以便组中的所有顶点/边缘都具有特定的标签。 例如,一个图形可以有多个标签为“person”的顶点。

图形数据库通常包含在 NoSQL 或非关系数据库类别中,因为不存在对架构或受约束数据模型的依赖。 由于缺乏架构,因此可以自然且高效地建模和存储连接的结构。

图形数据库示例

我们使用一个示例图形来了解如何在 Gremlin 中表示查询。 下图显示了一个商业应用程序,该应用程序管理以图形形式呈现的有关用户、兴趣和设备的数据。

显示人员、设备和兴趣的示例属性图。

此图形使用以下顶点类型。 这些类型在 Gremlin 中又称为“标签”:

  • 人员:图形中包含三名人员:Robin、Thomas 和 Ben。

  • 兴趣:人员的兴趣,在此示例中包括足球比赛。

  • 设备:人员使用的设备。

  • 操作系统:设备运行的操作系统。

  • 位置:从中访问设备的位置。

我们通过以下边缘类型表示这些实体之间的关系:

  • 关系:表示人际关系。 例如“Thomas 认识 Robin”。

  • 兴趣:表示图形中人员的兴趣。 例如“Ben 对足球很感兴趣”。

  • RunsOS:表示设备运行的 OS。 例如“笔记本电脑运行 Windows OS”。

  • 使用:表示人员使用哪种设备。 例如“Robin 使用序列号为 77 的摩托罗拉手机”。

  • 位置:表示从中访问设备的位置。

Gremlin 控制台是 Apache TinkerPop 提供的交互式终端,此终端用于与图形数据进行交互。 有关详细信息,请参阅 Gremlin 控制台快速入门。 也可以所选的平台(Java、Node.js、Python 或 .NET)中使用 Gremlin 驱动程序执行这些操作。 下面的示例演示如何使用 Gremlin 控制台对此图形数据运行查询。

首先了解创建、读取、更新和删除 (CRUD)。 以下 Gremlin 语句在图形中插入“Thomas”顶点,并附带一些属性

g.addV('person').
  property('id', 'thomas.1').
  property('firstName', 'Thomas').
  property('lastName', 'Andersen').
  property('age', 44)

提示

如果按照这些示例进行操作,则在创建图时可以将这些属性(agefirstNamelastName)中的任何一个用作分区键。 不支持将 id 属性用作图中的分区键。

接下来,以下 Gremlin 语句在 Thomas 与 Robin 之间插入“knows”边缘。

g.V('thomas.1').
  addE('knows').
  to(g.V('robin.1'))

以下查询按人员名字的降序返回“person”顶点:

g.V().
  hasLabel('person').
  order().
  by('firstName', decr)

如果需要回答类似于“Thomas 的朋友使用哪些操作系统?”的问题,图形可以提供很大的方便。 可以运行此 Gremlin 遍历从图形中获取该信息:

g.V('thomas.1').
  out('knows').
  out('uses').
  out('runsos').
  group().
  by('name').
  by(count())

后续步骤