美文网首页
Dgraph概念

Dgraph概念

作者: 羽_da59 | 来源:发表于2018-03-12 18:14 被阅读0次

1.概念

1.1 XID <-> UID

所有实体会被分配一个唯一的64位整型id,即UID。如果某个尸体有一个外部id(external id),即XID,DGraph会取出XID的指纹,并保存对应的UID。如果某个实体没有XID,DGraph只会添加一个新的UID,并标明这个UID已用。所有的posting list都通过UID引用实体。由于UID是8字节的整数,这种数据表示非常高效。在数据导入的时候,我们需要每个唯一的实体有一个唯一的UID。

1.2 Edges

典型的数据格式是RDF NQuad:

  • 主语(Subject), 谓语(Predicate), 宾语(Object), 标签(Label), aka
  • 实体(Entity), 属性(Attribute), 另一个实体或值(Other Entity / Value),标签(Label)

两种专门用语在Dgraph的代码里可以交替使用。Dgraph的edge是有向的,例如Subject -> Object。这也是查询执行的方向

可以自动生成一个反向的边。如果用户想按相反的方向执行查询,需要将reverse edge定义为schema的一部分

在Dgraph内部,RDF NQuad倍解析为下面的格式:

type DirectedEdge struct {
  Entity      uint64
  Attr        string
  Value       []byte
  ValueType   uint32
  ValueId     uint64
  Label       string
  Lang        string
  Op          DirectedEdge_Op // Set or Delete
  Facets      []*facetsp.Facet
}

不考虑输入的话,Entity以及 Object/ValueId都通过上面的XID <-> UID被转化成UID格式。

1.3 Posting List

概念上,posting list包含与一个Attribute关联的所有有向边,通过如下格式:

Attribute: Entity -> sorted list of ValueId 
//Everything in uint64 representation.

例如,如果我们存储一个朋友的列表,例如:

Entity Attribute ValueId
Me friend person0
Me friend person1
Me friend person2
Me friend person3

那么,将生成一个friend的posting list。在这个PL中查找Me会生成一个friend的列表,即[person0, person1, person2, person3]

拥有这个结构的一个很大优势是可以把需要做一个join的所有数据保存在一个PL中。这意味着,一个到持有PL的服务器RPC调用的结果是一个连接,而不需要更多的网络调用,减少查询需要的连接

顾名思义,PL是Posting的列表,用Protocol Buffers表示的话,它是这个样子:

message Posting {
  fixed64 uid = 1;
  bytes value = 2;
  enum ValType {
    DEFAULT = 0;
    BINARY = 1;
    INT = 2; // We treat it as int64.
    FLOAT = 3;
    BOOL = 4;
    DATE = 5;
    DATETIME = 6;
    GEO = 7;
    UID = 8;
    PASSWORD = 9;
    STRING = 10;

  }
  ValType val_type = 3;
  enum PostingType {
    REF=0;          // UID
    VALUE=1;        // simple, plain value
    VALUE_LANG=2;   // value with specified language
    // VALUE_TIMESERIES=3; // value from timeseries, with specified timestamp
  }
  PostingType posting_type = 4;
  bytes metadata = 5; // for VALUE_LANG: Language, for VALUE_TIMESERIES: timestamp, etc..
  string label = 6;
  uint64 commit = 7;  // More inclination towards smaller values.
  repeated facetsp.Facet facets = 8;

  // TODO: op is only used temporarily. See if we can remove it from here.
  uint32 op = 12;
}

message PostingList {
  repeated Posting postings = 1;
  bytes checksum = 2;
  uint64 commit = 3; // More inclination towards smaller values.
}

Dgraph中的所有数据都会首先使用Protocol Buffers序列化为字节数组后被存储或传输。当结果被返回给用户的时候,protocol buffer对象会被转换为JSON对象

在一个PL中通常有超过一个的Posting

RDF标签在每个posting中用label表示

现在Dgraph还不能通过查询获得label,但是将来会可以的

1.4 Badger

PostingList是通过Badger提供服务的,BadgerDB是一个嵌入式的、持久化的、简单的快速键值数据库,它使用纯Go语言开发.BadgerDB决定应该从内存、SSD或磁盘上提供多少数据。此外,它还支持在key上使用布隆过滤器,使随机查询的效率更高

为了让Badger对内存有完全的访问权限,以优化cache,每台服务器上都有一个Badger。每个实例包含这台服务器上的所有posting list

Posting list在Badger上以键值对的格式存储,例如:

(Predicate, Subject) --> PostingList

1.5 Group

包含同一个谓语(Predicate)的那些Posting list组成了一个group。每台服务器可以存储多个不同的group。

Group的配置文件用于确定每台服务器应该保存哪些group。在将来的版本中,在线的Dgraph服务器将可以使用探试法(heuristics)移动标签(tablets)

如果某个group变的太大,它可以被分割。在这种情况下,一个谓语实际上被分到两个group上,像下面这样:

Original Group:
            (Predicate, Sa..z)
  After split:
  Group 1:  (Predicate, Sa..i)
  Group 2:  (Predicate, Sj..z)

注意,这些key是被存储在RocksDB里的,因此group的split将会保持排序。例如,按字段顺序排序,在主语(subject)之前的被分到一个分组里,在主语之后的分到另一个分组里

1.6 复制与服务器故障

如果可能的话,每个group至少需要被三个服务器保存。当某台服务器故障时,其他保存同一个group数据的服务器可以继续提供服务

1.7 新服务器及发现

Dgraph集群可以自动检测加入到集群中的新服务器,建立连接,并将新服务器应该保存的group数据发过去

1.8 预写日志

对数据库的写入不会立马通过RocksDB写到磁盘上,而是先写到磁盘上的预写日志(Write ahead logs)里,这样可以避免posting list的经常重建

1.9 修改

除了被写入预写日志之外,对数据库的修改还会被存储在内存中,作为不可变的Posting list之上的一个可变层。它允许用户遍历Postings,仿佛它们是被排过序的,而无需重建posting list

当一个posting list在内存中有被修改后,它被视为dirty的。Dgraph会周期性地重新生成不可变的版本,并将改变写入RocksDB。注意,写入RocksDB的过程是异步的,这意味着它们并不会立刻被刷写到磁盘,但在服务器宕机的时候,这可能会导致数据丢失。但是不用担心,在Posting list被初始化的时候,会读取预写日志,这时丢失的数据会被补上

每当重新生成posting list的时候,Dgraph还会写一个包含最后一次提交日志的时间戳,用来决定在初始化posting list的时候从预写日志回溯多久的数据。(Every time we regenerate a posting list, we also write the max commit log timestamp that was included – this helps us figure out how long back to seek in write-ahead logs when initializing the posting list, the first time it’s brought back into memory.)

1.10 事务

Dgraph现在还不支持事务。

0.9版本已经支持事务

With the availability of transactions, a user can query for data, and then write their mods back atomically. Thus, upsert and mutation variables can be done via client-side logic, instead of baking this limiting functionality in the server.

一个修改可以由多条边组成,每条边可能属于不同的Posting list。Dgraph需要RWMutex来提供posting list上的锁。而在多个posting list上不存在锁

这意味着,一些边会比其他边先写入,而这时候读的话,只能读到部分被提交的数据。但是,还是有一致性保证的,当一个mutation成功的时候,任何成功的读操作都可以读到所有被更新的数据

如果一个mutation失败了,由用户决定是擦出部分写入的数据,还是用正确的逻辑重写。Dgraph的回复会说清楚哪些边没有被写入成功,用户可以设置正确的边来重新写入

局限性:

  • 你应该考虑好是否你的读操作需要原子性的事务。除非你需要处理财务数据,这不是Dgraph的适用场景
  • 为了保证原子性,每个mutation只能有一条边(RDF NQuads) 。这意味需要在clent及server之间反复地执行多次网络调用,这将影响你的写入吞吐量,但是会使错误处理的逻辑变得更简单

1.11版本

大体上来说,Dgraph存储有两种类型的数据,一种是关系(relationship)数据,一种是值

 Me friend person0    [Relation]
 Me name "Константи́н" [Value]

DGraph保存Posting list的方式,

2.最小化网络调用

相关文章

  • Dgraph概念

    1.概念 1.1 XID <-> UID 所有实体会被分配一个唯一的64位整型id,即UID。如果某个尸体有一个外...

  • dgraph安装

    nohup /opt/dgraph/dgraph-ratel -port 8050 > ratel.log 2>&...

  • Dgraph事务详解

    Dgraph是可扩展的,分布式的,低延迟图形数据库,采用badger作为存储引擎。DGraph 的目标是提供 Go...

  • Dgraph部署

    部署 本文讨论以分布式的模式运行Dgraph,包括运行多实例的Dgraph,并将多个server构建成一个集群 1...

  • dgraph编译

    基于CentOS 7.9 x64环境 安装epel yum install epel-release -y 安装必...

  • 从 dgraph-io/dgraph 了解 etcd/raft

    0. Intro 0.1 raft raft 是一种分布式一致性算法. 简单来说, raft 的使用场景是 log...

  • 从 dgraph-io/dgraph 了解 etcd/raft

    本次代码阅读基于commit 189fdd3 1. raftwal godoc 之前提到, etcd/raft提供...

  • DGraph批量写入

  • Dgraph-Take a tour

    Take a Tour Dgraph的GraphQL+-是一种基于facebook的GraphQL的图查询语言。G...

  • Dgraph-查询语言

    查询语言 Dgraph的GraphQL+-是一种基于facebook的GraphQL的图查询语言。GraphQL并...

网友评论

      本文标题:Dgraph概念

      本文链接:https://www.haomeiwen.com/subject/mrkofftx.html