Dgraph概念

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.最小化网络调用

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

推荐阅读更多精彩内容