• Go语言对etcd的基本操作


      本文简单介绍Go语言对etcd v3的基本操作。

    1. Import package
    import (
        "github.com/coreos/etcd/clientv3"
        "github.com/coreos/etcd/mvcc/mvccpb"
    )
    
    2. Declare Variables
    var cli *clientv3.Client
    
    var serverList = []string{
        "192.168.3.102:2379",
        "192.168.3.105:2379",
        "192.168.3.103:2379",
    }
    var userName = "root"
    var password = "shiajun666"
    var dialTimeout = 5
    var opTimeout = 5
    
    3. Connect to etcd server
    var err error
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   serverList,
        DialTimeout: time.Duration(dialTimeout) * time.Second,
        Username:    userName,
        Password:    password,
    })
    if err != nil {
        fmt.Println("Connect etcd server failed: ", err)
        return
    }
    
    4. Get
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    key := "name"
    resp, err := cli.Get(ctx, key)
    if err != nil {
        fmt.Printf("Get key[%s] failed: %v
    ", key, err)
        return
    }
    if len(resp.Kvs) == 0 {
        fmt.Printf("Key[%s] not exists.
    ", key)
        return
    }
    
    fmt.Println("value: ", string(resp.Kvs[0].Value))
    
    Get 方法的返回值如下:
    其中 Header *ResponseHeader 几乎是etcd所有方法返回值中都会包含的,它包含了集群ID、etcd节点成员ID、key全局版本号、raft任期号:
    Kvs []*mvccpb.KeyValue 包含多个键值对的信息,几乎etcd所有方法返回的键值对信息都由 mvccpb.KeyValue 表示,其结构如下:
     
    5. Get values according to key prefix
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    prefix := "name"
    resp, err := cli.Get(ctx, prefix, clientv3.WithPrefix())
    if err != nil {
        fmt.Printf("Get key prefix[%s] failed: %v
    ", prefix, err)
        return
    }
    if len(resp.Kvs) == 0 {
        fmt.Printf("Key prefix[%s] not exists.
    ", prefix)
        return
    }
    
    fmt.Println("values: ", resp.Kvs)
    
    6. put
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    key := "name"
    value := "shiajun"
    _, err = cli.Put(ctx, key, value)
    if err != nil {
        fmt.Printf("Put key[%s] value[%s] failed: %v
    ", key, value, err)
        return
    }
    fmt.Println("put success")
    
    Put 方法返回值如下:
    prevKv 表示当前Put操作执行之前该key的键值对信息,Put方法第四个参数加上 clientv3.WithPrevKV() 即可返回该信息,如下一个例子所示。
     
    7. put new value and get prev value
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    key := "name"
    value := "shiajun"
    opts := []clientv3.OpOption{clientv3.WithPrevKV()}
    resp, err := cli.Put(ctx, key, value, opts...)
    if err != nil {
        fmt.Printf("Put key[%s] value[%s] failed: %v
    ", key, value, err)
        return
    }
    fmt.Println("prev value: ", string(resp.PrevKv.Value))
    
    8. put with lease
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    //grant lease
    var ttl int64 = 10
    lease, err := cli.Grant(ctx, ttl)
    if err != nil {
        fmt.Printf("Grant lease failed: %v
    ", err)
    }
    
    //put with lease
    key := "name"
    value := "shiajun"
    _, err = cli.Put(ctx, key, value, clientv3.WithLease(lease.ID))
    if err != nil {
        fmt.Printf("Put key[%s] value[%s] with lease[%s] failed: %v
    ", key, value, lease.ID, err)
    }
    
    fmt.Println("put with lease success")
    
    Grant 方法返回值如下:
     
     
    9. put with lease and keep alive
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    //grant lease
    var ttl int64 = 10
    lease, err := cli.Grant(ctx, ttl)
    if err != nil {
        fmt.Printf("Grant lease failed: %v
    ", err)
    }
    
    //put with lease
    key := "name"
    value := "shiajun"
    _, err = cli.Put(ctx, key, value, clientv3.WithLease(lease.ID))
    if err != nil {
        fmt.Printf("Put key[%s] value[%s] with lease[%s] failed: %v
    ", key, value, lease.ID, err)
    }
    
    //keep alive
    kaCh, err := cli.KeepAlive(context.Background(), lease.ID)
    if err != nil {
        fmt.Printf("Keep alive key[%s] value[%s] with lease[%s] failed: %v
    ", key, value, lease.ID, err)
    }
    for {
        kaResp := <-kaCh
        fmt.Println("ttl: ", kaResp.TTL)
    }
    
    KeepAlive 方法返回值为一个channel:<-chan *LeaseKeepAliveResponse,接收每一次 keep alive 的结果返回:
     
    10. delete
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    key := "name"
    _, err = cli.Delete(ctx, key)
    if err != nil {
        fmt.Printf("Delete key[%s] failed: %v
    ", key, err)
        return
    }
    fmt.Println("delete success")
    
    Delete 方法返回值如下:
     
    11. watch
    key := "name"
    opts := []clientv3.OpOption{clientv3.WithPrevKV(), clientv3.WithPrefix()}
    wCh := cli.Watch(context.Background(), key, opts...)
    for resp := range wCh {
        for _, event := range resp.Events {
            if event.Type == mvccpb.PUT {
                fmt.Println("put happens")
            } else if event.Type == mvccpb.DELETE {
                fmt.Println("delete happens")
            }
            fmt.Println("prev value: ", event.PrevKv)
            fmt.Println("value: ", event.Kv)
        }
    }
    
    Watch 方法返回值为一个Channel:<-chan WatchResponse,接收watch的结果信息:
    对watch的key进行put、delete操作,watch操作即可获得变更结果,示例如下:
     
    12. compare and set - transation
    ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second)
    defer cancel()
    
    key := "number"
    kvc := clientv3.NewKV(cli)
    resp, err := kvc.Txn(ctx).
        If(clientv3.Compare(clientv3.Value(key), ">", "0")).
        Then(clientv3.OpPut(key, "100")).
        Else(clientv3.OpPut(key, "99")).
        Commit()
    if err != nil {
        fmt.Errorf("Compare and set transation failed: %v
    ", err)
    }
    
    fmt.Println(resp.Succeeded)
    
    这是使用etcd事务实现的一个先比较再赋值的简单例子:若 number 的值大于0,则将number赋值为100,否则赋值为99。
     
     

  • 相关阅读:
    基于Visual C++2013拆解世界五百强面试题--题13-找最大公共子字符串
    基于Visual C++2013拆解世界五百强面试题--题12-进制转换
    Color颜色对照表
    根据选择打开相应的程序
    复制一个5G文件只需要两秒,全网最牛方法!
    判断一个男人穷还是富,只看这几点!
    判断一个男人穷还是富,只看这几点!
    判断一个男人穷还是富,只看这几点!
    16年国庆假期期间兼职所悟
    16年国庆假期期间兼职所悟
  • 原文地址:https://www.cnblogs.com/wujuntian/p/15130668.html
Copyright © 2020-2023  润新知