• dgraph 使用简介


    dgraph 简介

    dgraph 是基于 golang 开发的开源的分布式图数据库. 诞生时间不长, 发展却很迅速. 目前是 v20.x 版本, dgraph 集群主要包含 3 种节点:

    1. Zero: 是集群的核心, 负责调度集群服务器和平衡服务器组之间的数据
    2. Alpha: 保存数据的 谓词索引. 谓词包括数据的 属性 和数据之间的 关系; 索引是为了更快的进行数据的过滤和查找
    3. Ratel: dgraph 的 UI 接口, 可以在此界面上进行数据的 CURD, 也可以修改数据的 schema

    通过增加 Alpha 的数量完成 dgraph 的水平扩展.

    dgraph 是 golang 开发的, 所以部署非常简单, 更简单的方式是使用 docker

    docker pull dgraph/dgraph:latest
    

    然后配置一个 docker-comopse.yml, 一键启动 dgraph 服务:

    version: "3.2"
    services:
      zero:
        image: dgraph/dgraph:latest
        volumes:
          - type: volume
            source: dgraph
            target: /dgraph
            volume:
              nocopy: true
        ports:
          - 5080:5080
          - 6080:6080
        restart: on-failure
        command: dgraph zero --my=zero:5080
      alpha:
        image: dgraph/dgraph:latest
        volumes:
          - type: volume
            source: dgraph
            target: /dgraph
            volume:
              nocopy: true
        ports:
          - 7080:7080
          - 8080:8080
          - 9080:9080
        restart: on-failure
        command: dgraph alpha --my=alpha:7080 --lru_mb=2048 --zero=zero:5080
      ratel:
        image: dgraph/dgraph:latest
        volumes:
          - type: volume
            source: dgraph
            target: /dgraph
            volume:
              nocopy: true
        ports:
          - 8000:8000
        command: dgraph-ratel
    
    volumes:
      dgraph:
    

    启动 dgraph, 在上面 docker-compose.yml 相同的文件夹下执行:

    docker-compose up -d
    

    如果没有错误, 可以通过: http://<YOUR IP/Domain>:8000/ 来访问 draph 的 UI 界面.

    dgraph 使用示例(基于 golang)

    通过 dgraph 的 UI 界面, 可以完成所有的操作, 但要想将 dgraph 和应用结合, 还得使用 dgraph 的 SDK.
    dgraph 的 SDK 支持各种语言, 官方支持的主要有: Go, C#, Java, Javascript, Python.

    dgraph 本身就是基于 golang 开发的, 所以对 Go 的支持肯定最全面, 下面就使用 golang 的 client 来演示 dgraph 的操作.

    golang client 安装

    安装最新版的 client:

    go get github.com/dgraph-io/dgo/v200
    

    创建 schema

    代码:

     1  func NewDgraphClient() *dgo.Dgraph {
     2   conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
     3   if err != nil {
     4     log.Fatal(err)
     5   }
     6  
     7   client := dgo.NewDgraphClient(api.NewDgraphClient(conn))
     8  
     9   return client
    10  }
    11  
    12  func CreateSchema(client *dgo.Dgraph) error {
    13   schema := `
    14  name: string @index(term) .
    15  age: int .
    16  
    17  type Person {
    18    name
    19    age
    20  }
    21  `
    22   op := &api.Operation{Schema: schema}
    23  
    24   err := client.Alter(context.Background(), op)
    25   return err
    26  }
    

    执行成功后, 在 UI 界面(http://localhost:8000)上验证是否创建成功:

    schema(pred:[name, age]) {
      perdicate
      type
      index
    }
    

    结果如下:

    {
      "data": {
        "schema": [
          {
            "predicate": "age",
            "type": "int"
          },
          {
            "predicate": "name",
            "type": "string",
            "index": true
          }
        ]
      },
      ... 省略 ...
    }
    

    数据的 CURD

    首先, 新增数据

     1  type Person struct {
     2   Uid     string   `json:"uid"`
     3   Name    string   `json:"name"`
     4   Age     int      `json:"age"`
     5   Friends []Person `json:"friends"`
     6  }
     7  
     8  func AddSomeData(client *dgo.Dgraph) error {
     9   p1 := &Person{
    10     Name: "Dog",
    11     Age:  10,
    12   }
    13   p1.Friends = make([]Person, 0)
    14  
    15   p2 := &Person{
    16     Name: "Monkey",
    17     Age:  20,
    18   }
    19   p3 := &Person{
    20     Name: "Cat",
    21     Age:  30,
    22   }
    23  
    24   p1.Friends = append(p1.Friends, *p2)
    25   p1.Friends = append(p1.Friends, *p3)
    26  
    27   mu := &api.Mutation{CommitNow: true}
    28   pb, err := json.Marshal(p1)
    29   if err != nil {
    30     return err
    31   }
    32  
    33   mu.SetJson = pb
    34   _, err = client.NewTxn().Mutate(context.Background(), mu)
    35   return err
    36  }
    

    查询数据:

     1  func QueryData(client *dgo.Dgraph) error {
     2   q := `
     3  query q($name: string){
     4      q(func:allofterms(name, $name)){
     5          name
     6          age
     7          uid
     8          friends{
     9              name
    10              age
    11              uid
    12          }
    13      }
    14  }
    15  `
    16   txn := client.NewTxn()
    17   res, err := txn.QueryWithVars(context.Background(), q, map[string]string{"$name": "Dog"})
    18   if err != nil {
    19     return err
    20   }
    21   fmt.Println(res.String())
    22   return nil
    23  }
    

    为了简化, 返回值中我直接打印了 string 格式, 其实返回的是个 json 结构.
    可以看出, 返回值中包含了上一步创建的 3 个 Person, 其中 2 个作为 Dog 的 friends 返回的.

    更新数据:

    1  func UpdateData(client *dgo.Dgraph) error {
    2   mu := &api.Mutation{
    3     CommitNow: true,
    4     SetNquads: []byte(`<0xfffd8d67d832b975> <age> "12" .`),
    5   }
    6  
    7   _, err := client.NewTxn().Mutate(context.Background(), mu)
    8   return err
    9  }
    

    其中 <0xfffd8d67d832b975> 是数据的 uid, 根据上面 query 示例的返回值中可以查找到.
    这里需要注意的是, 虽然是 int 类型, 但是它的值要用 双引号 围住.

    删除数据(删除数据的一个属性):

    1  func DeleteProp(client *dgo.Dgraph) error {
    2   mu := &api.Mutation{
    3     CommitNow: true,
    4     DelNquads: []byte(`<0xfffd8d67d832b976> <age> * .`),
    5   }
    6  
    7   _, err := client.NewTxn().Mutate(context.Background(), mu)
    8   return err
    9  }
    

    删除了 <0xfffd8d67d832b976> 这条数据的 属性, <0xfffd8d67d832b976> 是上面 name="Monkey" 的那条数据.

    将数据的属性和关系都删除之后, 这条数据就相当于删除了.
    直接根据 Uid 删除数据的 api 也有, 但是使用后无效(具体我提了个 issue 到 dgraph 的代码库)

    事务

    draph 是支持事务的, 上面的例子中其实已经使用了事务, 只不过每个事务中只有一个操作.
    如果有多个操作, 类似下面这样的代码即可:

     1  ctx := context.Background()
     2  tnx := client.NewTxn()
     3  
     4  _, err := tnx.Mutate(ctx, mu1)
     5  if err !=  nil {
     6         tnx.Discard(ctx)
     7  }
     8  _, err = tnx.Mutate(ctx, mu2)
     9  if err !=  nil {
    10         tnx.Discard(ctx)
    11  }
    12  
    13  tnx.Commit(ctx)
    

    总结

    图数据库不是万能的, 它的目的也不是取代关系数据库.
    我们根据使用场景在合适的时候选用 dgraph, 可以更加的轻松的完成数据分析, 而不用深陷 sql 的坑中.

  • 相关阅读:
    laravel队列
    php程序内存优化之数组操作优化
    swoole4创建Mysql连接池
    MySQL创建索引
    mysql索引命中规则
    Redis数据类型及使用场景
    Redis高可用集群-哨兵模式(Redis-Sentinel)
    网站架构优化性能
    PHP实现Redis分布式锁
    微软公司面试题
  • 原文地址:https://www.cnblogs.com/wang_yb/p/13204729.html
Copyright © 2020-2023  润新知