Dgraph部署

部署

本文讨论以分布式的模式运行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,并等待所有写入完成
  • 删除pw目录,然后
  • 重启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的一半

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

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,893评论 2 89
  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,813评论 0 5
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 一、人群画像 1、核心用户为80/90后的高学历男性 2、不同年龄用户热议内容 00后关注偶像及周边;80后更关注...
    chris_418c阅读 311评论 0 0
  • 27岁不算年轻但也不会太懵懂的年纪,身边朋友到27岁的大多孩子都几个了。身处着的21世纪,一点都不亚于当年上海滩的...
    遇见子美一一阅读 754评论 3 7