etcd 是一个高可用强一致性的键值仓库在很多分布式系统架构中得到了广泛的应用,其最经典的使用场景就是服务发现。etcd 中应该尽量只存储系统中服务的配置信息,对于应用数据只推荐把数据量很小,但是更新和访问频次都很高的数据存储在 etcd 中。


下载etcd

1
2
3
4
5
6
7
https://github.com/etcd-io/etcd/releases/download/v3.5.6/etcd-v3.5.6-linux-amd64.tar.gz
tar -zxvf etcd-v3.5.6-linux-amd64.tar.gz
cd etcd-v3.5.6-linux-amd64
mv etcd etcdctl etcdutl /usr/bin/

#查看版本
etcd -version

集群安装

节点一(10.0.0.56)

1
etcd --name=node1 --data-dir=/data/etcd/default.etcd  --initial-advertise-peer-urls http://10.0.0.100:2380 --listen-peer-urls http://10.0.0.100:2380 --listen-client-urls http://10.0.0.100:2379 --advertise-client-urls http://10.0.0.100:2379 --initial-cluster node1=http://10.0.0.100:2380,node2=http://10.0.0.101:2380 --initial-cluster-state new --initial-cluster-token 123456

节点二(10.0.0.199)

1
etcd --name=node2 --data-dir=/data/etcd/default.etcd  --initial-advertise-peer-urls http://10.0.0.101:2380 --listen-peer-urls http://10.0.0.101:2380 --listen-client-urls http://10.0.0.101:2379 --advertise-client-urls http://10.0.0.101:2379 --initial-cluster node1=http://10.0.0.100:2380,node2=http://10.0.0.101:2380 --initial-cluster-state new --initial-cluster-token 123456

集群模式下客户端命令行

查看成员列表

1
ETCDCTL_API=3 etcdctl --endpoints=10.0.0.100:2379,10.0.0.101:2379 member list

查看节点状态

1
ETCDCTL_API=3 etcdctl --endpoints=10.0.0.100:2379,10.0.0.101:2379 endpoint status --write-out=table

向集群中设置值

1
2
3
ETCDCTL_API=3 etcdctl --endpoints=10.0.0.100:2379,10.0.0.101:2379 put  api_56  "10.0.0.56:18080"

ETCDCTL_API=3 etcdctl --endpoints=10.0.0.100:2379,10.0.0.101:2379 put  api_109  "10.0.0.199:18080"

获取集群中的值

1
ETCDCTL_API=3 etcdctl --endpoints=10.0.0.100:2379,10.0.0.101:2379  get api --prefix

删除集群中数据

1
ETCDCTL_API=3 etcdctl --endpoints=10.0.0.100:2379,10.0.0.101:2379 del  key

go etcd使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package main

import (
    "context"
    "fmt"
    "log"
    "time"

    clientv3 "go.etcd.io/etcd/client/v3"
)

func main() {
    cli, err := clientv3.New(clientv3.Config{
        Endpoints:   []string{"10.0.0.100:2379", "10.0.0.101:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        log.Println(err)
    }
    defer cli.Close()

    key := "api/devops"
    put(cli, key, "10.0.0.110:3800")

    get(cli, key)

    select {}
}

func get(cli *clientv3.Client, key string) {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    resp, err := cli.Get(ctx, key)
    cancel()
    if err != nil {
        log.Fatal(err)
    }
    for _, ev := range resp.Kvs {
        fmt.Printf("%s : %s\n", ev.Key, ev.Value)
    }
}

func put(cli *clientv3.Client, key, value string) {
    resp, err := cli.Grant(context.TODO(), 5)
    if err != nil {
        log.Fatal(err)
    }

    _, err = cli.Put(context.TODO(), key, value, clientv3.WithLease(resp.ID))
    if err != nil {
        log.Fatal(err)
    }

    //  the key 'api/devops' will be kept forever
    ch, kaerr := cli.KeepAlive(context.TODO(), resp.ID)
    if kaerr != nil {
        log.Fatal(kaerr)
    }

    ka := <-ch
    if ka != nil {
        fmt.Println("ttl:", ka.TTL)
    } else {
        fmt.Println("Unexpected NULL")
    }
}