其他分享
首页 > 其他分享> > nebula入门学习——day1 nebula基本概念、原理和架构

nebula入门学习——day1 nebula基本概念、原理和架构

作者:互联网

什么是 Nebula Graph

Nebula Graph 是一款开源的、分布式的、易扩展的原生图数据库,能够承载包含数千亿个点和数万亿条边的超大规模数据集,并且提供毫秒级查询。

Nebula Graph 鸟瞰图

什么是图数据库

图数据库是专门存储庞大的图形网络并从中检索信息的数据库。它可以将图中的数据高效存储为点(Vertex)和边(Edge),还可以将属性(Property)附加到点和边上。

What is a graph database

图数据库适合存储大多数从现实抽象出的数据类型。世界上几乎所有领域的事物都有内在联系,像关系型数据库这样的建模系统会提取实体之间的关系,并将关系单独存储到表和列中,而实体的类型和属性存储在其他列甚至其他表中,这使得数据管理费时费力。

Nebula Graph 作为一个典型的图数据库,可以将丰富的关系通过边及其类型和属性自然地呈现。

Nebula Graph 的优势

开源

Nebula Graph 是在 Apache 2.0 条款下开发的。越来越多的人,如数据库开发人员、数据科学家、安全专家、算法工程师,都参与到 Nebula Graph 的设计和开发中来,欢迎访问 Nebula Graph GitHub 主页参与开源项目。

高性能

基于图数据库的特性使用 C++ 编写的 Nebula Graph,可以提供毫秒级查询。众多数据库中,Nebula Graph 在图数据服务领域展现了卓越的性能,数据规模越大,Nebula Graph 优势就越大。详情请参见 Nebula Graph benchmarking 页面

易扩展

Nebula Graph 采用 shared-nothing 架构,支持在不停止数据库服务的情况下扩缩容。

易开发

Nebula Graph 提供 Java、Python、C++ 和 Go 等流行编程语言的客户端,更多客户端仍在开发中。详情请参见 Nebula Graph clients

高可靠访问控制

Nebula Graph 支持严格的角色访问控制和 LDAP(Lightweight Directory Access Protocol)等外部认证服务,能够有效提高数据安全性。详情请参见验证和授权

生态多样化

Nebula Graph 开放了越来越多的原生工具,例如 Nebula StudioNebula ConsoleNebula Exchange 等,更多工具可以查看生态工具概览

此外,Nebula Graph 还具备与 Spark、Flink、HBase 等产品整合的能力,在这个充满挑战与机遇的时代,大大增强了自身的竞争力。

兼容 openCypher 查询语言

Nebula Graph 查询语言,简称为 nGQL,是一种声明性的、部分兼容 openCypher 的文本查询语言,易于理解和使用。详细语法请参见 nGQL 指南

面向未来硬件,读写平衡

闪存型设备有着极高的性能,并且价格快速下降, Nebula Graph 是一个面向 SSD 设计的产品,相比于基于 HDD + 大内存的产品,更适合面向未来的硬件趋势,也更容易做到读写平衡。

灵活数据建模

用户可以轻松地在 Nebula Graph 中建立数据模型,不必将数据强制转换为关系表。而且可以自由增加、更新和删除属性。详情请参见数据模型

广受欢迎

腾讯、美团、京东、快手、360 等科技巨头都在使用 Nebula Graph。详情请参见 Nebula Graph 官网

适用场景

Nebula Graph 可用于各种基于图的业务场景。为节约转换各类数据到关系型数据库的时间,以及避免复杂查询,建议使用 Nebula Graph。

欺诈检测

金融机构必须仔细研究大量的交易信息,才能检测出潜在的金融欺诈行为,并了解某个欺诈行为和设备的内在关联。这种场景可以通过图来建模,然后借助 Nebula Graph,可以很容易地检测出诈骗团伙或其他复杂诈骗行为。

实时推荐

Nebula Graph 能够及时处理访问者产生的实时信息,并且精准推送文章、视频、产品和服务。

知识图谱

自然语言可以转化为知识图谱,存储在 Nebula Graph 中。用自然语言组织的问题可以通过智能问答系统中的语义解析器进行解析并重新组织,然后从知识图谱中检索出问题的可能答案,提供给提问人。

社交网络

人际关系信息是典型的图数据,Nebula Graph 可以轻松处理数十亿人和数万亿人际关系的社交网络信息,并在海量并发的情况下,提供快速的好友推荐和工作岗位查询。

Nebula Graph 架构总览

Nebula Graph 由三种服务构成:Graph 服务、Meta 服务和 Storage 服务,是一种存储与计算分离的架构。

每个服务都有可执行的二进制文件和对应进程,用户可以使用这些二进制文件在一个或多个计算机上部署 Nebula Graph 集群。

下图展示了 Nebula Graph 集群的经典架构。

Nebula Graph architecture

Meta 服务

在 Nebula Graph 架构中,Meta 服务是由 nebula-metad 进程提供的,负责数据管理,例如 Schema 操作、集群管理和用户权限管理等。

Meta 服务的详细说明,请参见 Meta 服务

Graph 服务和 Storage 服务

Nebula Graph 采用计算存储分离架构。Graph 服务负责处理计算请求,Storage 服务负责存储数据。它们由不同的进程提供,Graph 服务是由 nebula-graphd 进程提供,Storage 服务是由 nebula-storaged 进程提供。计算存储分离架构的优势如下:

Graph 服务和 Storage 服务的详细说明,请参见 Graph 服务Storage 服务

Meta 服务

本文介绍 Meta 服务的架构和功能。

Meta 服务架构

The architecture of the Meta Service

Meta 服务是由 nebula-metad 进程提供的,用户可以根据场景配置 nebula-metad 进程数量:

所有 nebula-metad 进程构成了基于 Raft 协议的集群,其中一个进程是 leader,其他进程都是 follower。

leader 是由多数派选举出来,只有 leader 能够对客户端或其他组件提供服务,其他 follower 作为候补,如果 leader 出现故障,会在所有 follower 中选举出新的 leader。

Note

leader 和 follower 的数据通过 Raft 协议保持一致,因此 leader 故障和选举新 leader 不会导致数据不一致。更多关于 Raft 的介绍见 Storage 服务

Meta 服务功能

管理用户账号

Meta 服务中存储了用户的账号和权限信息,当客户端通过账号发送请求给 Meta 服务,Meta 服务会检查账号信息,以及该账号是否有对应的请求权限。

更多 Nebula Graph 的访问控制说明,请参见身份验证

管理分片

Meta 服务负责存储和管理分片的位置信息,并且保证分片的负载均衡。

管理图空间

Nebula Graph 支持多个图空间,不同图空间内的数据是安全隔离的。Meta 服务存储所有图空间的元数据(非完整数据),并跟踪数据的变更,例如增加或删除图空间。

管理 Schema 信息

Nebula Graph 是强类型图数据库,它的 Schema 包括 Tag、Edge type、Tag 属性和 Edge type 属性。

Meta 服务中存储了 Schema 信息,同时还负责 Schema 的添加、修改和删除,并记录它们的版本。

更多 Nebula Graph 的 Schema 信息,请参见数据模型

管理 TTL 信息

Meta 服务存储 TTL(Time To Live)定义信息,可以用于设置数据生命周期。数据过期后,会由 Storage 服务进行处理,具体过程参见 TTL

管理作业

Meta 服务中的作业管理模块负责作业的创建、排队、查询和删除。

 

Graph 服务

Graph 服务主要负责处理查询请求,包括解析查询语句、校验语句、生成执行计划以及按照执行计划执行四个大步骤,本文将基于这些步骤介绍 Graph 服务。=-=》mapreduce就靠他了!

Graph 服务架构

The architecture of the Graph Service

查询请求发送到 Graph 服务后,会由如下模块依次处理:

  1. Parser:词法语法解析模块。

  2. Validator:语义校验模块。

  3. Planner:执行计划与优化器模块。

  4. Executor:执行引擎模块。

Parser

Parser 模块收到请求后,通过 Flex(词法分析工具)和 Bison(语法分析工具)生成的词法语法解析器,将语句转换为抽象语法树(AST),在语法解析阶段会拦截不符合语法规则的语句。

例如GO FROM "Tim" OVER like WHERE properties(edge).likeness > 8.0 YIELD dst(edge)语句转换的 AST 如下。

AST

Validator

Validator 模块对生成的 AST 进行语义校验,主要包括:

校验完成后,Validator 模块还会生成一个默认可执行,但是未进行优化的执行计划,存储在目录 src/planner 内。

Planner

如果配置文件 nebula-graphd.confenable_optimizer 设置为 false,Planner 模块不会优化 Validator 模块生成的执行计划,而是直接交给 Executor 模块执行。

如果配置文件 nebula-graphd.confenable_optimizer 设置为 true,Planner 模块会对 Validator 模块生成的执行计划进行优化。如下图所示。

Optimizer

Executor

Executor 模块包含调度器(Scheduler)和执行器(Executor),通过调度器调度执行计划,让执行器根据执行计划生成对应的执行算子,从叶子节点开始执行,直到根节点结束。如下图所示。

Executor

每一个执行计划节点都一一对应一个执行算子,节点的输入输出在优化执行计划时已经确定,每个算子只需要拿到输入变量中的值进行计算,最后将计算结果放入对应的输出变量中即可,所以只需要从节点 Start 一步步执行,最后一个算子的输出变量会作为最终结果返回给客户端。

代码结构

Nebula Graph 的代码层次结构如下:

 
|--src
   |--context    //校验期和执行期上下文
   |--daemons
   |--executor   //执行算子
   |--mock
   |--optimizer  //优化规则
   |--parser     //词法语法分析
   |--planner    //执行计划结构
   |--scheduler  //调度器
   |--service
   |--util       //基础组件
   |--validator  //语句校验
   |--visitor

Storage 服务

Nebula Graph 的存储包含两个部分,一个是 Meta 相关的存储,称为 Meta 服务,在前文已有介绍。

另一个是具体数据相关的存储,称为 Storage 服务。其运行在 nebula-storaged 进程中。本文仅介绍 Storage 服务的架构设计。

优势

Storage 服务架构

image

Storage 服务是由 nebula-storaged 进程提供的,用户可以根据场景配置 nebula-storaged 进程数量,例如测试环境 1 个,生产环境 3 个。

所有 nebula-storaged 进程构成了基于 Raft 协议的集群,整个服务架构可以分为三层,从上到下依次为:

下文将基于架构介绍 Storage 服务的部分特性。

Storage 写入流程

image

KVStore

Nebula Graph 使用自行开发的 KVStore,而不是其他开源 KVStore,原因如下:

基于上述原因,Nebula Graph 使用 RocksDB 作为本地存储引擎,实现了自己的 KVStore,有如下优势:

数据存储格式

图存储的主要数据是点和边,Nebula Graph 将点和边的信息存储为 key,同时将点和边的属性信息存储在 value 中,以便更高效地使用属性过滤。

属性说明

Nebula Graph 使用强类型 Schema。

对于点或边的属性信息,Nebula Graph 会将属性信息编码后按顺序存储。由于属性的长度是固定的,查询时可以根据偏移量快速查询。在解码之前,需要先从 Meta 服务中查询具体的 Schema 信息(并缓存)。同时为了支持在线变更 Schema,在编码属性时,会加入对应的 Schema 版本信息。

数据分片

由于超大规模关系网络的节点数量高达百亿到千亿,而边的数量更会高达万亿,即使仅存储点和边两者也远大于一般服务器的容量。因此需要有方法将图元素切割,并存储在不同逻辑分片(Partition)上。Nebula Graph 采用边分割的方式。

data partitioning

切边与存储放大

Nebula Graph 中逻辑上的一条边对应着硬盘上的两个键值对(key-value pair),在边的数量和属性较多时,存储放大现象较明显。边的存储方式如下图所示。

edge storage

上图以最简单的两个点和一条边为例,起点 SrcVertex 通过边 EdgeA 连接目的点 DstVertex,形成路径(SrcVertex)-[EdgeA]->(DstVertex)。这两个点和一条边会以 6 个键值对的形式保存在存储层的两个不同分片,即 Partition x 和 Partition y 中,详细说明如下:

EdgeA_Out 和 EdgeA_In 以方向相反的两条边的形式存在于存储层,二者组合成了逻辑上的一条边 EdgeA。EdgeA_Out 用于从起点开始的遍历请求,例如(a)-[]->();EdgeA_In 用于指向目的点的遍历请求,或者说从目的点开始,沿着边的方向逆序进行的遍历请求,例如例如()-[]->(a)

如 EdgeA_Out 和 EdgeA_In 一样,Nebula Graph 冗余了存储每条边的信息,导致存储边所需的实际空间翻倍。因为边对应的 key 占用的硬盘空间较小,但 value 占用的空间与属性值的长度和数量成正比,所以,当边的属性值较大或数量较多时候,硬盘空间占用量会比较大。

如果对边进行操作,为了保证两个键值对的最终一致性,可以开启 TOSS 功能,开启后,会先在正向边所在的分片进行操作,然后在反向边所在分片进行操作,最后返回结果。

分片算法

分片策略采用静态 Hash 的方式,即对点 VID 进行取模操作,同一个点的所有 Tag、出边和入边信息都会存储到同一个分片,这种方式极大地提升了查询效率。

Note

创建图空间时需指定分片数量,分片数量设置后无法修改,建议设置时提前满足业务将来的扩容需求。

多机集群部署时,分片分布在集群内的不同机器上。分片数量在 CREATE SPACE 语句中指定,此后不可更改。

如果需要将某些点放置在相同的分片(例如在一台机器上),可以参考公式或代码

下文用简单代码说明 VID 和分片的关系。

 
// 如果 ID 长度为 8,为了兼容 1.0,将数据类型视为 int64。
uint64_t vid = 0;
if (id.size() == 8) {
    memcpy(static_cast<void*>(&vid), id.data(), 8);
} else {
    MurmurHash2 hash;
    vid = hash(id.data());
}
PartitionID pId = vid % numParts + 1;

简单来说,上述代码是将一个固定的字符串进行哈希计算,转换成数据类型为 int64 的数字(int64 数字的哈希计算结果是数字本身),将数字取模,然后加 1,即:

 
pId = vid % numParts + 1;

示例的部分参数说明如下。

参数说明
% 取模运算。
numParts VID所在图空间的分片数,即 CREATE SPACE 语句中的partition_num值。
pId VID所在分片的 ID。

例如有 100 个分片,VID为 1、101 和 1001 的三个点将会存储在相同的分片。分片 ID 和机器地址之间的映射是随机的,所以不能假定任何两个分片位于同一台机器上。

与 HDFS 的区别

Storage 服务基于 Raft 协议实现的分布式架构,与 HDFS 的分布式架构有一些区别。例如:

总而言之,Storage 服务更加轻量级,精简了一些功能,架构没有 HDFS 复杂,可以有效提高小块存储的读写性能。


 

数据模型

本文介绍 Nebula Graph 的数据模型。数据模型是一种组织数据并说明它们如何相互关联的模型。

数据模型

Nebula Graph 数据模型使用 6 种基本的数据模型:

Note

Tag 和 Edge type 的作用,类似于关系型数据库中“点表”和“边表”的表结构。

有向属性图

Nebula Graph 使用有向属性图模型,指点和边构成的图,这些边是有方向的,点和边都可以有属性。

下表为篮球运动员数据集的结构示例,包括两种类型的点(playerteam)和两种类型的边(servefollow)。

类型名称属性名(数据类型)说明
Tag player name (string)
age(int)
表示球员。
Tag team name (string) 表示球队。
Edge type serve start_year (int)
end_year (int)
表示球员的行为。
该行为将球员和球队联系起来,方向是从球员到球队。
Edge type follow degree (int) 表示球员的行为。
该行为将两个球员联系起来,方向是从一个球员到另一个球员。

黄色部分不应该是点吗???奇怪。。。

 

Note

Nebula Graph 中没有无向边,只支持有向边。

Compatibility

由于 Nebula Graph 3.1.0 的数据模型中,允许存在"悬挂边",因此在增删时,用户需自行保证“一条边所对应的起点和终点”的存在性。详见 INSERT VERTEXDELETE VERTEXINSERT EDGEDELETE EDGE

不支持 openCypher 中的 MERGE 语句。

路径

图论中一个非常重要的概念是路径,路径是指一个有限或无限的边序列,这些边连接着一系列点。

路径的类型分为三种:walktrailpath。关于路径的详细说明,请参见维基百科

本文以下图为例进行简单介绍。

路径示例

walk

walk类型的路径由有限或无限的边序列构成。遍历时点和边可以重复。

查看示例图,由于 C、D、E 构成了一个环,因此该图包含无限个路径,例如A->B->C->D->EA->B->C->D->E->CA->B->C->D->E->C->D

Note

GO语句采用的是walk类型路径。

trail

trail类型的路径由有限的边序列构成。遍历时只有点可以重复,边不可以重复。柯尼斯堡七桥问题的路径类型就是trail

查看示例图,由于边不可以重复,所以该图包含有限个路径,最长路径由 5 条边组成:A->B->C->D->E->C

Note

MATCHFIND PATHGET SUBGRAPH语句采用的是trail类型路径。

在 trail 类型中,还有cyclecircuit两种特殊的路径类型,以下图为例对这两种特殊的路径类型进行介绍。

trail 示例

path

path类型的路径由有限的边序列构成。遍历时点和边都不可以重复。

查看示例图,由于点和边都不可以重复,所以该图包含有限个路径,最长路径由 4 条边组成:A->B->C->D->E

点 VID

在 Nebula Graph 中,一个点由点的 ID 唯一标识,即 VID 或 Vertex ID。

VID 的特点

VID 使用建议

VID 生成建议

VID 的生成工作完全交给应用端,有一些通用的建议:

定义和修改 VID 与其数据类型

VID 的数据类型必须在创建图空间时定义,且一旦定义无法修改。

VID 必须在插入点时设置,且一旦设置无法修改。

"查询起始点"(start vid) 与全局扫描

绝大多数情况下,Nebula Graph 的查询语句(MATCHGOLOOKUP)的执行计划,必须要通过一定方式找到查询起始点的 VID(start vid)。

定位 start vid 只有两种方式:

  1. 例如 GO FROM "player100" OVER 是在语句中显式的指明 start vid 是 "player100";

  2. 例如 LOOKUP ON player WHERE player.name == "Tony Parker" 或者 MATCH (v:player {name:"Tony Parker"}),是通过属性 player.name 的索引来定位到 start vid

Caution

match (n) return n; 会返回错误Scan vertices or edges need to specify a limit number, or limit number can not push down.,这是一个全局扫描,需要用LIMIT子句限制返回数量才能执行。

标签:存储,nebula,服务,VID,Graph,Nebula,Storage,day1,基本概念
来源: https://www.cnblogs.com/bonelee/p/16302332.html