目录

Dgraph备忘录

不定时补充更新

部署

 1docker pull dgraph/dgraph
 2# HOSTIPADDR=10.0.0.10 # 用以后续告知raft模块通信地址,确保集群连通性, 我这儿后面直接写了
 3cd ..
 4mkdir -p Dgraph
 5# 创建服务用户
 6groupadd dgraph
 7useradd -M -g dgraph -s /usr/sbin/nologin dgraph
 8chown -R dgraph:dgraph Dgraph
 9# 生成TLS证书
10# client证书用于mtls, SAN(Subject Alternative Name) 取决于访问时需要用到的标识(localhost, 公网IP...)
11docker run --rm -v ~/Dgraph:/dgraph dgraph/dgraph:latest dgraph cert -n $SAN -c zero1
12docker run --rm -v ~/Dgraph:/dgraph dgraph/dgraph:latest dgraph cert -c alpha1
13# zero
14docker run -d --name dgraph-zero-1 --network dgraph_default -p 6080:6080 -p 5080:5080 -v ~/Dgraph:/dgraph dgraph/dgraph:latest dgraph zero --my=10.0.0.10:5080 --tls "ca-cert=/dgraph/tls/ca.crt;client-auth-type=REQUIREANDVERIFY;server-cert=/dgraph/tls/node.crt;server-key=/dgraph/tls/node.key;internal-port=true;client-cert=/dgraph/tls/client.zero1.crt;client-key=/dgraph/tls/client.zero1.key"
15# alpha
16docker run -d --name dgraph-alpha1 --network dgraph_default -p 7080:7080 -p 9080:9080 -p 8080:8080 -v ~/Dgraph:/dgraph dgraph/dgraph:latest dgraph alpha --zero=10.0.0.10:5080 --my=10.0.0.10:7080 --badger "compression=zstd:1" --security "whitelist=0.0.0.0/0" --tls "ca-cert=/dgraph/tls/ca.crt;client-auth-type=REQUIREANDVERIFY;server-cert=/dgraph/tls/node.crt;server-key=/dgraph/tls/node.key;internal-port=true;client-cert=/dgraph/tls/client.alpha1.crt;client-key=/dgraph/tls/client.alpha1.key"
17# 给浏览器签发证书(自己导入ca.crt和.p12文件)
18# 同样的,可以给需要连接的客户端签发证书
19docker run --rm -v ~/Dgraph:/dgraph dgraph/dgraph:latest dgraph cert -c browser
20openssl pkcs12 -export -out Dgraph/browser.p12 -in Dgraph/tls/client.browser.crt -inkey Dgraph/tls/client.browser.key

端口占用情况:

Dgraph Node TypegRPC-internal-privategRPC-external-privategRPC-external-publicHTTP-external-privateHTTP-external-public
zero508050806080
alpha708090808080
ratel8000

Triples

Dgraph采用的图数据模型是Triples(三元组), 也即S P O, 展开表示为: <Subject> <Predicate> <Object>.

也即图中由subject标识的节点通过有向边predicate连接到object.

同时借助RDF(资源描述框架, 基于语义网的知识表示框架)来增强其数据关联性.

Blank UID

 1{
 2	set {
 3		_:alice <name> "Alice" .
 4		_:bob <name> "Bob"
 5		_:bob <follows> _:alice .
 6		# assign type
 7		_:alice <dgraph.type> "Person" .
 8    	_:bob <dgraph.type> "Person" .
 9	}
10}

_:alice 并不是真正的uid, 其在这里就是一个uidplaceholder(数据还未真正创建), 可以在set 阶段去引用某对象的uid.

Schema里的<>

简单来说, 如果你的predicate名并不是由数字及字母组成, 在执行mutation时就需要用<>括起来.

If your predicate is a URI or has language-specific characters, then enclose it with angle brackets <> when executing the schema mutation.

Expand a type

1{
2	data(func: type(Person)) {
3		expand(_all_) {
4			expand(_all_)
5		}
6	}
7}

通过指定type函数参数为某type, 会自动展开结果中该type的字段(predicate).

Reverse edges

predicate定义里加上@reverse, 可通过~来取反.

Password type

Dgraph提供了password类型, 表现为加密后的string, 其实是使用bcrypt加密生成的密文(60字节).

@upsert

predicate添加此directive, 以使提交事务时Dgraph可以检查索引是否有冲突, 从而达到unique index的效果.

1<email>: string @index(hash) @upsert .

使用upsert block:

  • 发起一个新事务
  • query, 如果成功返回了uid则说明该结点已经存在, 反则说明不存在
  • 若不存在, 则会创建新结点(紧接着的mutation)
 1upsert {
 2  query {
 3    q(func: eq(email, "[email protected]")) {
 4      v as uid
 5      name
 6    }
 7  }
 8
 9  mutation {
10    set { # 若uid有值
11      uid(v) <name> "first last" .
12      uid(v) <email> "[email protected]" .
13    }
14  }
15}

GraphQL & DQL

说实话, Dgraph的文档还是有些糟糕, 你所需的信息可能藏在你根本想不到的角落(尽量将所有文档概览一下), 这个主题来自这篇Blog.

早期Dgraph是直接使用GraphQL作为数据库查询语言, 但很显然, GraphQL设计的初衷是用于API的, 只是语法看起来很"graph", 所以很快就展现出了其局限性:

A DQL schema is predicate-first focused and supports some aspects not yet supported by the GraphQL syntax such as multi-lingual predicates and facets (data information stored on edges between nodes).

A GraphQL schema is type-first focused and only supports spec-compliant elements.

DQLDgraph基于GraphQL魔改的一套适于图数据库原生的查询语言, 事实上Dgraph核心只使用DQL, 任何传入的GraphQL请求都会先被重写为DQL.

简单来说, 直接使用GraphQL Endpoint也未尝不可, Dgraph本身也可以是GraphQL Native, 但无论如何, 其内部还是使用的DQL, 其会据GraphQLschema'生成一份等同的DQL schema, 反之则不然.

GraphQL Endpoint可以配备访问权限控制(@auth directive... 等), DQL更适合传统的后端开发(先查询数据, 做点自定操作然后再返回).

数据存储

Dgraph数据使用Badger存储, 一个基于LSM-TreeKV数据库, 其设计使得它理论上能够很好的降低读写放大的问题.

Dgraph的图数据模型是Triples, 在存储时: 所有相同predicate的记录组成一个shard, 在该shard中, 具有同一<subject - predicate>关系的的记录会被组合浓缩成一条K-V对存储在Badger中. 该value又叫做posting list(搜索引擎术语, 根据搜索的term找到的排序好的文档ids). posting list作为一个value存储在Badger中, 而其keysubjectpredicate共同推导而得.

1<0x01> <follower> <0xab> .
2<0x01> <follower> <0xbc> .
3<0x01> <follower> <0xcd> .
4...
5key = <follower, 0x01>
6value = <0xab, 0xbc, 0xcd, ...>

Dgraph中你可以使用debug子命令来观察posting list结构:

1docker stop dgraph-alpha # 或复制一份p文件夹
2dgraph debug -p Dgrpah/p
3# 具体使用方法
4dgraph debug -h