etcd学习

etcd学习

  • 终端操作
    • put
    • get
    • del

etcd似乎是存在于k8s的底层,例如我们使用kubectl创建一个ReplicaSet的时候,这个指令会发送给kube-apiserver,也就是专门管理kubectl的服务,kube-apiserver接收到指令后,将ReplicaSet创建并保存到etcd中,etcd会给kube-apiserver发送一个对应的Create事件,

终端操作

put

应用程序通过 put 将 key 和 value 存储到 etcd 集群中。每个存储的密钥都通过 Raft 协议复制到所有 etcd 集群成员,以实现一致性和可靠性。

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/coreos/etcd/clientv3"
)

func main() {
	config := clientv3.Config{
		Endpoints:   []string{"127.0.0.1:2379"}, // 集群列表
		DialTimeout: 5 * time.Second,
	}

	// 建立一个客户端
	client, err := clientv3.New(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	// 用于读写etcd的键值对
	kv := clientv3.NewKV(client)
	
	// clientv3.WithPrevKV() 是一个可选控制项,用于获取在设置当前键值对之前的该键的键值对
	// 有了该控制项后,putResp 才有 PrevKv 的属性,即获取之前的键值对。
	// context.TODO() 表示当前还不知道用哪个 context 控制该操作,先用该字段占位
	putResp, err := kv.Put(context.TODO(), "/demo/A/B", "hello", clientv3.WithPrevKV())

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println("putResp is ", putResp)
	fmt.Println("Revision:", putResp.Header.Revision)
	if putResp.PrevKv != nil {
		fmt.Println("PrevValue:", string(putResp.PrevKv.Value))
	}
	putResp, err = kv.Put(context.TODO(),"/test/key1", "Hello etcd!")
	if err != nil{
		fmt.print("put failed!")
	}
	kv.Put(context.TODO(),"/test/key2", "Hello World!")
	// 再写一个同前缀的干扰项
	kv.Put(context.TODO(), "/testspam", "spam")
}


get

函数声明如下:

// Get retrieves keys.
// By default, Get will return the value for "key", if any.
// When passed WithRange(end), Get will return the keys in the range [key, end).
// When passed WithFromKey(), Get returns keys greater than or equal to key.
// When passed WithRev(rev) with rev > 0, Get retrieves keys at the given revision;
// if the required revision is compacted, the request will fail with ErrCompacted .
// When passed WithLimit(limit), the number of returned keys is bounded by limit.
// When passed WithSort(), the keys will be sorted.
Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error)

这里 err 并不能反馈出 key 是否存在(只能反馈出本次操作因为各种原因异常了),我们需要通过 GetResponse 判断 key 是否存在

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/coreos/etcd/clientv3"
)

func main() {
	config := clientv3.Config{
		Endpoints:   []string{"192.168.0.113:2379"}, // 集群列表
		DialTimeout: 5 * time.Second,
	}

	// 建立一个客户端
	client, err := clientv3.New(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	// 用于读写etcd的键值对
	kv := clientv3.NewKV(client)

	kv.Put(context.TODO(), "/demo/A/B", "BBB", clientv3.WithPrevKV())
	kv.Put(context.TODO(), "/demo/A/C", "CCC", clientv3.WithPrevKV())
	// 	读取/demo/A/为前缀的所有key
	// clientv3.WithPrefix() , clientv3.WithCountOnly() 可以有多个并以 逗号分隔即可
	getResp, err := kv.Get(context.TODO(), "/demo/A/", clientv3.WithPrefix() /*,clientv3.WithCountOnly()*/)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(getResp.Kvs, getResp.Count)
	for _, resp := range getResp.Kvs {
		fmt.Printf("key: %s, value:%s\n", string(resp.Key), string(resp.Value))
	}
}

del

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/coreos/etcd/clientv3"
)

func main() {
	config := clientv3.Config{
		Endpoints:   []string{"192.168.0.113:2379"}, // 集群列表
		DialTimeout: 5 * time.Second,
	}

	// 建立一个客户端
	client, err := clientv3.New(config)
	if err != nil {
		fmt.Println(err)
		return
	}

	// 用于读写etcd的键值对
	kv := clientv3.NewKV(client)

	kv.Put(context.TODO(), "/demo/A/B1", "BBB", clientv3.WithPrevKV())
	kv.Put(context.TODO(), "/demo/A/B2", "CCC", clientv3.WithPrevKV())
	kv.Put(context.TODO(), "/demo/A/B3", "DDD", clientv3.WithPrevKV())
	/*
		clientv3.WithFromKey() 表示针对的key操作是大于等于当前给定的key
		clientv3.WithPrevKV() 表示返回的 response 中含有之前删除的值,否则
		下面的 delResp.PrevKvs 为空
	*/
	delResp, err := kv.Delete(context.TODO(), "/demo/A/B",
		clientv3.WithFromKey(), clientv3.WithPrevKV())
	if err != nil {
		fmt.Println(err)
	}
	// 查看被删除的 key 和 value 是什么
	if delResp.PrevKvs != nil {
		// if len(delResp.PrevKvs) != 0 {
		for _, kvpair := range delResp.PrevKvs {
			fmt.Println("已删除:", string(kvpair.Key), string(kvpair.Value))
		}
	}
}

你可能感兴趣的:(k8s学习,etcd,学习,golang)