参考文章
官网:https://etcd.io/
godoc文档:https://pkg.go.dev/go.etcd.io/etcd/clientv3?tab=doc
参考文章:https://www.liwenzhou.com/posts/Go/go_etcd/
git地址:https://github.com/etcd-io/etcd/releases
etcd是使用Go语言开发的一个开源的、高可用的分布式key-value存储系统,可以用于配置共享和服务的注册和发现。
ETCD_VER=v3.4.8
# choose either URL
GOOGLE_URL=https://storage.googleapis.com/etcd
GITHUB_URL=https://github.com/etcd-io/etcd/releases/download
DOWNLOAD_URL=${GOOGLE_URL}
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test
curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1
rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz
/tmp/etcd-download-test/etcd --version
/tmp/etcd-download-test/etcdctl version
# start a local etcd server
/tmp/etcd-download-test/etcd
# 开启远程服务
/tmp/etcd-download-test/etcd --listen-client-urls 'http://0.0.0.0:2379' --advertise-client-urls 'http://0.0.0.0:2379' --initial-advertise-peer-urls http://0.0.0.0:2380 --listen-peer-urls 'http://0.0.0.0:2380' > out.txt &
# write,read to etcd
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 put foo bar
/tmp/etcd-download-test/etcdctl --endpoints=localhost:2379 get foo
go get go.etcd.io/etcd/clientv3
由于grpc包的升级和更改,如果go build时报如下错误
E:\goproject\gotest\redistest>go run mian.go
# github.com/coreos/etcd/clientv3/balancer/resolver/endpoint
C:\Users\18322\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\resolver\endpoint\endpoint.go:114:78: undefined: resolver.BuildOption
C:\Users\18322\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\resolver\endpoint\endpoint.go:182:31: undefined: resolver.ResolveNowOption
# github.com/coreos/etcd/clientv3/balancer/picker
C:\Users\18322\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\picker\err.go:37:44: undefined: balancer.PickOptions
C:\Users\18322\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\picker\roundrobin_balanced.go:55:54: undefined: balancer.PickOptions
修改go.mod 文件,降低grpc版本
replace google.golang.org/grpc => google.golang.org/grpc v1.26.0
//replace github.com/lucas-clemente/quic-go => github.com/lucas-clemente/quic-go v0.14.1
type EtcdManage struct {
Client *clientv3.Client
RequestTimeout time.Duration
}
//新建一个etcd实例
func NewEtcdManage(addrs []string)*EtcdManage{
em := new(EtcdManage)
//连接etcd远程服务
client,err := clientv3.New(clientv3.Config{
Endpoints:addrs,
DialTimeout: time.Second * 5,
})
if err!=nil{
panic(err)
}
em.Client = client
em.RequestTimeout = time.Second * 3
return em
}
//设置kv
func (e * EtcdManage)Put(key,value string)error{
ctx,cancel := context.WithTimeout(context.Background(),e.RequestTimeout)
_,err := e.Client.Put(ctx,key,value)
cancel()
return err
}
//获取kv
func (e * EtcdManage)Get(key string)(value []string,err error){
ctx,cancel := context.WithTimeout(context.Background(),e.RequestTimeout)
getresp,err := e.Client.Get(ctx,key)
cancel()
if err!=nil{
return nil,err
}
kvs := make([]string,0)
//将所有的值拼接成企切片,然后取出
for i,value := range getresp.Kvs{
fmt.Println(string(value.Key),string(value.Value))
kvs = append(kvs,string(getresp.Kvs[i].Value))
}
return kvs,nil
}
//删除
func (e * EtcdManage)Delete(key string)error{
_,err := e.Client.Delete(context.TODO(),key)
return err
}
func (e * EtcdManage)Close()error{
return e.Client.Close()
}
func InitEtcd(){
key := "etcd_test"
em := NewEtcdManage([]string{"192.168.254.172:2379"})
defer em.Close()
err := em.Put(key,"this is second test value")
if err!=nil{
fmt.Println("put:",err)
return
}
values,err := em.Get(key)
if err!=nil{
fmt.Println("get",err)
return
}
fmt.Println(values)
}
监测某个key,当key变化时,回调函数
添加一个成员函数
//添加一个watch注册函数,非阻塞
func (e * EtcdManage)Watch(key string,f func(w clientv3.WatchResponse)bool){
//开始监听key值得变化
watchchan := e.Client.Watch(context.Background(),key)
go func(){
for {
if event,ok := <- watchchan;!ok{
break
}else{
if !f(event) {
return
}
}
}
}()
}
改造测试函数
func InitEtcd(){
key := "etcd_test"
em := NewEtcdManage([]string{"192.168.254.172:2379"})
defer em.Close()
//实现一个watch函数
em.Watch(key,func(e clientv3.WatchResponse)bool{
for _,event := range e.Events{
fmt.Println(event.Type,string(event.Kv.Key),string(event.Kv.Value))
}
return true
})
err := em.Put(key,"this is second test value")
if err!=nil{
fmt.Println("put:",err)
return
}
values,err := em.Get(key)
if err!=nil{
fmt.Println("get",err)
return
}
fmt.Println(values)
select {
}
}
创建一个租约成员函数
//timeout: 多少秒后过期
func (e * EtcdManage)Grant(key,value string,timeout int64)(clientv3.LeaseID,error){
lrr,err:=e.Client.Grant(context.TODO(),timeout)
if err!=nil{
return 0,err
}
_,err =e.Client.Put(context.TODO(),key,value,clientv3.WithLease(lrr.ID))
return lrr.ID,err
}
keepalive 会让key租约失效,会一直保存下去
func (e * EtcdManage)KeepAlive(lid clientv3.LeaseID)error{
_,err := e.Client.KeepAlive(context.TODO(),lid)
return err
}
未完待续…