部署
本文讨论以分布式的模式运行Dgraph,包括运行多实例的Dgraph,并将多个server构建成一个集群
1. 安装Dgraph
到github上下载需要的发行版,并解压即可
2.简单集群构建
2.1 理解Dgraph集群
Dgraph是一个真正的分布式图数据库,而不是以master-slave模式复制数据全集的。它根据谓语分片,并在集群中备份谓语,查询可以在任何节点上执行,连接是基于分布式的数据执行的。查询节点自己存储的谓语会在本地执行,而对于存在其他节点上的谓语,会使用分布式的join
为了更有效地运行Dgraph集群,理解shard、replica以及rebalance时怎么工作的很重要
2.1.1 Sharding
Dgraph把每个谓语(在RDF术语中写作* P *)的数据存在一起,因此最小的数据单元时一个谓语。为了把图分片,需要把一个或多个谓语分配到一个group。集群中的每个节点都存有一个group,zero负责把group分配给各个节点
2.1.2 Shard rebalancing
Dgraph的zero会试着基于磁盘使用情况进行rebalance。如果Zero检测到数据分布不平衡的情况,它会试着把某个谓语以及它的index、反向边一起转移到磁盘使用最少的group上。这可能会导致这个谓语暂时不可用
Zero会不断地检查数据分布,每十分钟一次。因此,每个的Dgraph实例都会允许Zero从group中分离某个谓语,并将它转移到一个新的节点上
2.1.3 一致性Replication
如果把--replicas
标志设置为大于一的整数,Zero会把group分配到多个node上。这些节点将组成一个Raft group,被称作quorum。每个写操作将会被一致地复制到quorum上。为了保证数据一致性,quorum的大小应该时奇数。因此,我们推荐把--replicas
设置为1、3或5。这允许0、1或者2个存储同一个group的节点宕机而不影响group的健康
2.2 直接在host上跑
2.2.1 运行dgraph zero
$ dgraph zero --my=IPADDR:7080 --wal zw
默认的Zero端口是7080与8080,7080时Dgraph集群内部不同节点之间数据交互的Grpc端口,而8080是与外部程序数据交互的HTTP端口。你可以使用--port_offset
标志改变这些端口
--my
标志是Dgraph与zero联系的拨号盘,因此端口7080
以及IP地址必须对其他Dgraph服务器是可见的
如果想查看所有可用的flag,执行:dgraph zero --help
2.2.2 运行dgraph server
dgraph server --idx=2 --memory_mb=<typically half the RAM>
--my=IPADDR:7081 --zero=localhost:7080 --port_offset=1
Dgraph服务器监听内部端口7080,以及外部HTTP端口8080、外部Grpc端口9080。这些可以通过--port_offset
标志指定
注意--idx
标志可以省略,省略的话Zero将会自动地为每个Dgraph server分配一个唯一的ID,Dgraph服务器会将它持久化到wal目录中
可以使用-p
与-w
修改文件及WAL的存储位置,具体可以执行dgraph server --help
2.2.3 运行Dgraph UI
$ dgraph-ratel -p 8081
Dgraph UI默认监听8081端口,可以使用-p
标志来修改。默认情况下,ratel会假设dgraph在localhost:8080端口运行,可以在ui中修改这个地址
注意 ratel需要访问Amazon下载css与js
2.3 高可用性配置
在高可用性配置中,我们需要运行三个或五个Zero,以及三个或五个server
注意
如果replica的数量是2K+1,至多K个server宕机的情况下,读写可以不受任何影响
避免把replica设置为2K(偶数),这样如果K个服务器宕机,将会导致阻塞读写
2.3.1 Dgraph Zero
运行三个实例,并通过--idx
给每一个分配一个唯一ID,并通过--peer
发送一个健康的Zero实例的地址(会自动加入集群?像redis那样?)
为了让server实例保存三个复制,设置--replicas=3
。每当添加一个新的Dgraph服务器,Zero将会检查已有的group,并给它们分配一个复制数不是三的group
依次启动三个zero:
./dgraph zero --idx 100 --port_offset 100 --my 10.181.105.100:7180 --wal ../data/zw --replicas 3
./dgraph zero --idx 101 --port_offset 100 --my 10.181.105.101:7180 --peer 10.181.105.100:7180 --wal ../data/zw --replicas 3
./dgraph zero --idx 102 --port_offset 100 --my 10.181.105.102:7180 --peer 10.181.105.101:7180 --wal ../data/zw --replicas 3
2.3.2 Dgraph Server
Run as many Dgraph servers as you want。可以手动设置--idx
标志,如果不设的话也可以,Zero 会给server自动分配一个id。这个id将会被保存在wal中,所以不要删除wal
新的server会联系zero自动检测其他的server,并互相建立连接。通常,Zero首先会通过分配一个server运行已有的group来尝试复制一个group。如果所有的分组都已经安装 —replicas
标志复制好了,Zero会创建一个新的分组。随着时间的发展,数据会被均匀地被分割到不同的group中。因此,需要确保Dgraph server的数量是replication设置的整数倍。
例如,如果在Zero中设置--replicas=3
,那么运行三个server的话,不会有sharding,但是有3x的复制。如果运行六个serer,那么会把数据shard到两个group中,仍然有3x复制
依次启动三个server:
./dgraph server --idx 200 --port_offset 200 --memory_mb 51200 --my 10.181.105.100:7280 --zero 10.181.105.102:7180 --postings ../data/p --wal ../data/w
./dgraph server --idx 201 --port_offset 200 --memory_mb 51200 --my 10.181.105.101:7280 --zero 10.181.105.100:7180 --postings ../data/p --wal ../data/w
./dgraph server --idx 202 --port_offset 200 --memory_mb 51200 --my 10.181.105.102:7280 --zero 10.181.105.101:7180 --postings ../data/p --wal ../data/w
2.3.4 移除死节点
如果一个人复制坏掉,并且不能被恢复,可以移除它并向quorum中添加一个新节点。Zero中的/removeNode
可以用于移除死节点(/removeNode?id=3&group=2
)
注意
在使用API之前,必须先确定节点宕了,并确保它不会再恢复了
在添加新复制的时候,记得设置
idx
标志,否则Zero会给它设置一个新的分组
3. 从源码构建
确保安装了Go (version >= 1.8)
之后,执行:
# This should install dgraph binary in your $GOPATH/bin.
$ go get -u -v github.com/dgraph-io/dgraph/dgraph
如果在build的时候,报了grpc
的错,你的go-grpc
版本可能太老了。我们不提供go-groc
(因为在使用Go client的时候它会有问题)。通过运行如下命令更新go-grpc
:
$ go get -u -v google.golang.org/grpc
4. More about Dgraph
在http端口上,一个运行中的Dgraph实例有一系列的管理终端:
-
/
Browser UI and query visualization. -
/health
HTTP status code 200 and “OK” message if worker is running, HTTP 503 otherwise. -
/admin/shutdown
shutdown a node. -
/admin/export
take a running export.
默认情况下,server会监听localhost
(只有本机可见的本地环网地址),可以使用 --bindall=true
选项绑定到 0.0.0.0
,监听外部链接
注意 如果你准备load大量数据,把最大文件描述符设置为像10000这样的大值
5. More about Dgraph Zero
Dgraph Zero控制Dgraph集群。它会基于每个实例存储数据的大小自动地在集群中移动数据
在运行任何dgraph server
之前,必须至少有一个dgraph zero
- Zero存储集群的信息
-
--replicas
是控制复制因子的选项(例如每个数据分片的复制数,包括原始分片) - 每当一个新的机器启动,zero会基于复制因子给它分配一个group。如果复制因子是1,那么每个节点都会保存不同的group。如果复制因子是2,摒弃启动了4个节点,那么前面两个节点会保存group1,后面两个保存group2
- Zero也会监控每个group的谓语占用的空间大小,并会通过移动它们来平衡集群
像Dgrph一样,Zero也有使用HTTP端口8080(+port_offset)。可以通过查询它来获取有用的信息,如下:
-
/state
集群中节点的信息,包括谓语的size,以及它们所属的组 -
/removeNode?id=idx&group=gid
用于从quorum中移除死掉的节点,节点id与groupid是所需的参数
查看state信息:
{
"counter": "26",
"groups": {
"1": {
"members": {
"200": {
"id": "200",
"groupId": 1,
"addr": "10.181.105.100:7280",
"leader": true,
"lastUpdate": "1515398876"
},
"201": {
"id": "201",
"groupId": 1,
"addr": "10.181.105.101:7280"
},
"202": {
"id": "202",
"groupId": 1,
"addr": "10.181.105.102:7280"
}
},
"tablets": {
"_dummy_": {
"groupId": 1,
"predicate": "_dummy_",
"space": "19"
}
}
}
},
"zeros": {
"100": {
"id": "100",
"addr": "10.181.105.100:7180",
"leader": true
},
"101": {
"id": "101",
"addr": "10.181.105.101:7180"
},
"102": {
"id": "102",
"addr": "10.181.105.102:7180"
}
}
}
6. 配置
可以用--help
参数查看zero与server的所有配置项
可以通过多种方式进行配置(按优先级从高到低):
- 使用命令行标志
- 使用环境变量
- 使用配置文件
多种配置方式可以同时使用,例如配置文件用于保存核心信息,命令行标志用于为每个实例制定参数
环境变量本人不推荐使用,不翻译了
配置文件支持的格式包括JSON、TOML、YAML、HCL以及Java properties,通过文件扩展名识别
配置文件可以通过--config
标签或者环境变量指定,例如:
$ dgraph zero --config my_config.json
配置文件的结构就是简单的键值对,例如JSON格式配置文件如下:
{
"idx": 42,
"peer": 192.168.0.55:9080,
"replicas": 2
}
7. TSL配置
client到server之间的连接可以通过TLS提高安全,支持加密(密码保护)与非加密私钥
如果你使用
openssl
生成加密私钥,必须明确指定加密算法(例如-aes256)。这回强制openssl
在私钥中包含DEK-Info
头,这需要Dgraph解密key。如果使用默认加密方式,openssl
不会写头,因此key无法被解密
server有如下参数可以配置:
# Use TLS connections with clients.
tls_on
# CA Certs file path.
tls_ca_certs string
# Include System CA into CA Certs.
tls_use_system_ca
# Certificate file path.
tls_cert string
# Certificate key file path.
tls_cert_key string
# Certificate key passphrase.
tls_cert_key_passphrase string
# Enable TLS client authentication
tls_client_auth string
# TLS max version. (default "TLS12")
tls_max_version string
# TLS min version. (default "TLS11")
tls_min_version string
Dgraph loader可以通过如下参数设置:
# Use TLS connections.
tls_on
# CA Certs file path.
tls_ca_certs string
# Include System CA into CA Certs.
tls_use_system_ca
# Certificate file path.
tls_cert string
# Certificate key file path.
tls_cert_key string
# Certificate key passphrase.
tls_cert_key_passphrase string
# Server name.
tls_server_name string
# Skip certificate validation (insecure)
tls_insecure
# TLS max version. (default "TLS12")
tls_max_version string
# TLS min version. (default "TLS11")
tls_min_version string
8. 集群Checklist
在创建集群的时候,确保检查了如下项:
- 是不是至少一个dgraph zero节点在运行
- 是否集群中的每个实例都被正确配置
- 是不是每个实例都能通过7080 (+ any port offset)访问所有peer
- 是不是每个节点在启动的时候都有一个唯一ID
- 是不是设置了
--bindall=true
9. 快速数据导入
有两个工具可以进行数据批量导入:
dgraph live
dgraph bulk
注意
这两个工具都只能接受gzip压缩的RDF NQuad/Triple数据。其他格式的数据必须先转换
9.1 Live Loader
dgraph live
是一个从gzip压缩文件中读取RDF Nquads,把它们分批,使用go client创建mutation,并导入Dgraph的工具
Live loader可以正确地给多个文件中的空节点分配唯一ID,并将它们持久化到磁盘,以节省内存并应付loader重新执行的情况
$ dgraph live --help # To see the available flags.
# Read RDFs from the passed file, and send them to Dgraph on localhost:9080.
$ dgraph live -r <path-to-rdf-gzipped-file>
# Read RDFs and a schema file and send to Dgraph running at given address
$ dgraph live -r <path-to-rdf-gzipped-file> -s <path-to-schema-file> -d <dgraph-server-address:port>
9.2 Bulk Loader
注意
调整bulk loader的参数以提高性能非常重要
Bulk loader的功能与live loader很像,但是只能被用于dgraph离线,并准备初始化的情况。它不能运行在一个已有的dgraph实例
警告
千万不要在Dgraph服务启动的时候执行bulk loader。用它把已有的数据导入一个新的Dgraph实例
Bulk loader比live loader快相当多,但是它只被推荐用于大数据集初始化导入dgraph
可以参看read some technical details博客来了解技术细节
你需要决定集群中希望的dgraph实例的数量,并将reduce shard的数量设置为这个数。你还需要把map shard的数量至少设置为跟这个数相等(数量越大,bulk loader就会把谓语在reduce shard中分布的梗平均)
下面的例子,使用了2个reduce shard以及4个map shard:
dgraph-bulk-loader -r=goldendata.rdf.gz -s=goldendata.schema --map_shards=4 --reduce_shards=2
{
"RDFDir": "goldendata.rdf.gz",
"SchemaFile": "goldendata.schema",
"DgraphsDir": "out",
"LeaseFile": "LEASE",
"TmpDir": "tmp",
"NumGoroutines": 4,
"MapBufSize": 67108864,
"ExpandEdges": true,
"BlockRate": 0,
"SkipMapPhase": false,
"CleanupTmp": true,
"NumShufflers": 1,
"Version": false,
"MapShards": 4,
"ReduceShards": 2
}
MAP 01s rdf_count:219.0k rdf_speed:218.7k/sec edge_count:693.4k edge_speed:692.7k/sec
MAP 02s rdf_count:494.2k rdf_speed:247.0k/sec edge_count:1.596M edge_speed:797.7k/sec
MAP 03s rdf_count:749.4k rdf_speed:249.4k/sec edge_count:2.459M edge_speed:818.3k/sec
MAP 04s rdf_count:1.005M rdf_speed:250.8k/sec edge_count:3.308M edge_speed:826.1k/sec
MAP 05s rdf_count:1.121M rdf_speed:223.9k/sec edge_count:3.695M edge_speed:738.3k/sec
MAP 06s rdf_count:1.121M rdf_speed:186.6k/sec edge_count:3.695M edge_speed:615.3k/sec
MAP 07s rdf_count:1.121M rdf_speed:160.0k/sec edge_count:3.695M edge_speed:527.5k/sec
REDUCE 08s [22.68%] edge_count:837.9k edge_speed:837.9k/sec plist_count:450.2k plist_speed:450.2k/sec
REDUCE 09s [40.79%] edge_count:1.507M edge_speed:1.507M/sec plist_count:905.8k plist_speed:905.7k/sec
REDUCE 10s [79.91%] edge_count:2.953M edge_speed:1.476M/sec plist_count:1.395M plist_speed:697.3k/sec
REDUCE 11s [100.00%] edge_count:3.695M edge_speed:1.231M/sec plist_count:1.778M plist_speed:592.5k/sec
REDUCE 11s [100.00%] edge_count:3.695M edge_speed:1.182M/sec plist_count:1.778M plist_speed:568.8k/sec
Total: 11s
数据生成之后,你可以在启动server的时候使用-p
参数指定输出的目录。如果运行了多个Dgraph server,你需要把输出的shard拷贝到不同的服务器上
cd out/i # i = shard number.
dgraph server -zero=localhost:7080 -memory_mb=1024
9.2.1 性能调优
Tip
我们强烈推荐在执行Bulk Loader的时候禁用swap空间。修复参数减少内存使用,比swap导致loader宕机好
可以使用标志来控制bulk loader的行为及性能特点。可以使用dgraph bulk --help
查看所有的参数。特别要注意,需要调整参数使bulk loader不会使用超过RAM大小的内存。一旦开始swap,它将变的特别慢
Map
在map语句中,修改下面的参数可以降低内存使用:
-
--num_go_routines
标志控制worker线程的数量,数值越小,占用的内存越少 -
--mapoutput_mb
标志控制map输出文件的大小,数值越小,占用的内存越少
对于更大的数据集,以及有很多core的服务器,map中的gzip解码可能会成为瓶颈,可以首先把RDF拆分成多个.rdf.gz
文件(例如每个256MB)。这对内存使用会有略微的影响
Reduce
Reduce语句对内存的压力比map小,尽管它仍然可能会使用很多内存。有些参数可以提高性能,但是只有在你有很大的RAM的情况下使用:
-
--reduce_shards
控制产生的dgraph实例数。增大 - The
--map_shards
flag controls the number of separate map output shards. Increasing this increases memory consumption but balances the resultant dgraph instances more evenly. - The
--shufflers
controls the level of parallelism in the shuffle/reduce stage. Increasing this increases memory consumption.
10. 导出
可以访问集群中任意节点的终端,导出所有节点的数据:
$ curl localhost:8080/admin/export
Warning 如果从dgraph运行的服务器之外调用是无效的
Dgraph也提供了一个HTTP GET接口,可以在Dgraph运行的服务器上调用
这个接口可以导出集群中所有的group的数据。每个服务器都会把输出写入到gzip压缩的rdf文件,文件路径可以通过--export
参数指定。如果某个group失败了,所有的export进程都会失败,并返回错误
Note 用户需要自己到集群中的服务器上拿导出的数据文件,Dgraph不会把文件拷到执行导出的服务器
11. 关机
可以通过执行如下命令,将一个Dgraph节点的安全退出:
curl localhost:8080/admin/shutdown
Warning 如果从运行的dgraph之外的服务器执行是无效的
这会停止执行命令的服务器上的Dgraph,而不是停止整个Dgraph集群
12. 删除数据库
如果要删除所有的数据,可以使用Alter
终端的DropAll
请求
或者,你也可以:
- 关闭Dgraph,并等待所有写入完成
- 删除
p
与w
目录,然后 - 重启Dgraph
13. 升级Dgraph
周期性的数据导出是个好主意。特别是当你希望升级数据库,或者重新配置集群的分片时。下面是数据安全导出与重启的正确步骤:
- 开启一个导出任务
- 确保导出成功
- 关闭集群
- 使用新数据目录运行Dgraph
- 通过bulk loader重新导入数据
- 如果都成功了,你可以删除旧目录(数据导出是为了保证数据安全)
14. 监控
Dgraph通过/debug/vars
终端以json格式返回监控指标。Dgraph不存储监控指标,只是返回当时的值。你可以将数据存储在监控系统,或者安装Prometheus
将下面配置文件中的ip配置为你的dgraph实例,并用如下命令运行prometheus:
$ prometheus -config.file my_config.yaml
scrape_configs:
- job_name: "dgraph"
metrics_path: "/debug/prometheus_metrics"
scrape_interval: "2s"
static_configs:
- targets:
- 172.31.9.133:8080
- 172.31.15.230:8080
- 172.31.0.170:8080
- 172.31.8.118:8080
安装Grafana用于绘制监控指标。Grafana默认会在3000端口上运行。用如下步骤创建一个prometheus数据源。通过如下链接导入一个grafana_dashboard.json
15. Troubleshooting
下面是一些常见的问题及解决办法
15.1 OOM(out of memory)
在bulk loading数据的时候,Dgraph可能会消耗更多的内存,因为会有大量写入。因此你可能会遇到OOM问题
推荐的最小RAM是16GB。当使用默认的—memory_mb=4096
设置时,Dgraph可能会占用7-8GB
在EC2/GCE实例上,我们推荐最小RAM是8GB。推荐将-memory_mb
设置为RAM的一半