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 Type | gRPC-internal-private | gRPC-external-private | gRPC-external-public | HTTP-external-private | HTTP-external-public |
|---|---|---|---|---|---|
| zero | 5080 | 5080 | 6080 | ||
| alpha | 7080 | 9080 | 8080 | ||
| ratel | 8000 |
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, 其在这里就是一个uid的placeholder(数据还未真正创建), 可以在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.
DQL是Dgraph基于GraphQL魔改的一套适于图数据库原生的查询语言, 事实上Dgraph核心只使用DQL, 任何传入的GraphQL请求都会先被重写为DQL.
简单来说, 直接使用GraphQL Endpoint也未尝不可, Dgraph本身也可以是GraphQL Native, 但无论如何, 其内部还是使用的DQL, 其会据GraphQL的schema'生成一份等同的DQL schema, 反之则不然.
GraphQL Endpoint可以配备访问权限控制(@auth directive... 等), DQL更适合传统的后端开发(先查询数据, 做点自定操作然后再返回).
数据存储
Dgraph数据使用Badger存储, 一个基于LSM-Tree的KV数据库, 其设计使得它理论上能够很好的降低读写放大的问题.
Dgraph的图数据模型是Triples, 在存储时: 所有相同predicate的记录组成一个shard, 在该shard中, 具有同一<subject - predicate>关系的的记录会被组合浓缩成一条K-V对存储在Badger中. 该value又叫做posting list(搜索引擎术语, 根据搜索的term找到的排序好的文档ids). posting list作为一个value存储在Badger中, 而其key由subject及predicate共同推导而得.
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
