持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
前言
在使用Go语言进行开发或者k8s中,总能看见etcd
的身影,那么它是什么呢?下面就来学习一下
介绍
A distributed, reliable key-value store for the most critical data of a distributed system
根据官方的说法,etcd
是一个分布式、可靠的键值对的存储系统,同时etcd是使用Go来开发、开源的。通常用来当作注册中心、配置管理、分布式锁等,大多数情况下还是被用来做注册中心,即类似于Java微服务中的eureka
、zookeeper
等。
etcd
具有以下的一些特点:
- 高可用:集群中的每个节点都有完整的数据保存,避免某个单点故障所导致的数据丢失。
- 速度较快:每秒有近1w次的写入速度、1~10w次的读取速度
- 出色跨平台性:因为是Go语言开发,因此能够在多个平台上部署。
- 安全:通信支持SSL证书
- 可靠:基于Raft算法实现了强一致性、高可用的服务存储目录
PS: Raft是一个用于管理日志一致性的协议。
下载
我们去到官网进行下载相关平台的etcd:github.com/etcd-io/etc…
在这里我选择etcd-v3.5.5-windows-amd64.zip
的版本进行下载安装。
随后点击etcd.exe
进行启动excd的服务器,默认服务器处理请求的端口为2379
。
测试一下
需要注意V2
和V3
的命名并不兼容,这里使用的是V3常用的命令:
- 增改键值对:
etcdctl put KEY VALUE
- 获得对应键值对:
etcdctl get KEY
- 模糊查询前缀为PREFIX的数据:
etcdctl get --prefix PREFIX
- 删除对应键值对:
etcdctl del KEY
- 查看etcd版本:
etcdctl version
这里需要注意etcd
的存储格式、目前仅支持键值对,同时键以目录树的结构进行存储。
Go+etcd
下面使用Go来连接etcd来进行crud
引入依赖
- go get go.etcd.io/etcd/clientv3
- go get -u -x google.golang.org/grpc@v1.26.0
CRUD
func testEtcd() {
client, err := clientv3.New(clientv3.Config{Endpoints: []string{"localhost:2379"}})
if err != nil {
panic(err)
}
defer client.Close()
client.Put(GetTimeOutCtx(), "/demo/1", "just value") // put
getResp, _ := client.Get(GetTimeOutCtx(), "/demo/1") // get
for _, kv := range getResp.Kvs {
fmt.Printf("key=%s\tvalue=%s\n", kv.Key, kv.Value)
}
client.Delete(GetTimeOutCtx(), "/demo1/1") // delete
}
func GetTimeOutCtx() context.Context {
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
return ctx
}
前缀查询
func testPrefixGet() {
client, err := clientv3.New(clientv3.Config{Endpoints: []string{"localhost:2379"}})
if err != nil {
panic(err)
}
defer client.Close()
client.Put(GetTimeOutCtx(), "/demo/1", "1")
client.Put(GetTimeOutCtx(), "/demo/2", "2")
response, _ := client.Get(GetTimeOutCtx(), "/demo", clientv3.WithPrefix())
for _, kv := range response.Kvs {
fmt.Printf("key=%s\tvalue=%s\n", kv.Key, kv.Value)
}
}
// key=/demo/1 value=1
// key=/demo/2 value=2
监控watch
func testWatch() {
client, err := clientv3.New(clientv3.Config{Endpoints: []string{"localhost:2379"}})
if err != nil {
panic(err)
}
defer client.Close()
fmt.Println("start watch ...")
client.Put(GetTimeOutCtx(), "/demo/1", "oldValue") // 设置旧值
watch := client.Watch(context.Background(), "/demo/1") // 观察对应key,返回单向接受通道 <-chan WatchResponse
for response := range watch {
for _, kv := range response.Events {
fmt.Printf("key=%s\tnowValue=%s\n", kv.Kv.Key, kv.Kv.Value)
}
}
}
这时候我们打开客户端,执行etcdctl put /demo/1 newvalue
命令,会发现控制台输出啦~
它会一直监控,该通道不会自动关闭
key=/demo/1 nowValue=newvalue