go-etcd客户端操作

golang-etcd客户端操作

关于golang-etcd的所有api介绍和使用demo,可以参见 https://pkg.go.dev/go.etcd.io/etcd/client/v3#pkg-overview

 

1. 获取客户端连接

func main() {
config := clientv3.Config{
Endpoints: []string{"xxx.xxx.xxx.xxx:2379"},
DialTimeout: 5 * time.Second,
}
// 获取客户端连接
_, err := clientv3.New(config)
if err != nil {
fmt.Println(err)
return
}
}

 

clientv3.Config包含的常用配置信息及其释义如下:

Endpoints
[]string
etcd集群ip+port
DialTimeout
time.Duration
连接超时时间
DialKeepAliveTimeout
time.Duration
客户端keepalive超时时间
DialKeepAliveTime
time.Duration
查看是否正常服务
MaxCallSendMsgSize
int 客户端请求的最大字节限制,默认2MiB
MaxCallRecvMsgSize
int 客户端响应的最大字节限制,默认math.MaxInt32
Username
string 用户名
Password string 密码

 

2. PUT操作

// 用于写etcd的键值对
kv := clientv3.NewKV(client)
// PUT请求,clientv3.WithPrevKV()表示获取上一个版本的kv
putResp, err := kv.Put(context.TODO(), "/cron/jobs/job1", "hello",clientv3.WithPrevKV())
if err != nil {
fmt.Println(err)
return
}
// 获取版本号
fmt.Println("Revision:", putResp.Header.Revision)
// 如果有上一个kv 返回kv的值
if putResp.PrevKv != nil {
fmt.Println("PrevValue:", string(putResp.PrevKv.Value))
}

kv.Put()参数列表解释:

  • 第一个参数为context,可以自己设置可取消和自动过期的context
  • 第二个参数为key
  • 第三个参数为value
  • 后面的参数可选,with开头,支持多种功能,具体可以参考所有with的文档

 

3. GET操作

// 用于读写etcd的键值对
kv := clientv3.NewKV(client)
// 简单的get操作
getResp, err := kv.Get(context.TODO(), "cron/jobs/job1", clientv3.WithCountOnly())
if err != nil {
fmt.Println(err)
return
}
fmt.Println(getResp.Count)

 

4. DELETE操作

// 用于写etcd的键值对
kv := clientv3.NewKV(client)
// 读取cron/jobs下的所有key
getResp, err := kv.Get(context.TODO(), "/cron/jobs", clientv3.WithPrefix())
if err != nil {
fmt.Println(err)
return
}
// 获取目录下所有key-value
fmt.Println(getResp.Kvs)

 

// 用于读写etcd的键值对
kv := clientv3.NewKV(client)
// 删除指定kv
delResp, err := kv.Delete(context.TODO(), "/cron/jobs/job1", clientv3.WithPrevKV())
if err != nil {
fmt.Println(err)
return
}
// 被删除之前的value是什么
if len(delResp.PrevKvs) != 0 {
for _, kvpair := range delResp.PrevKvs {
fmt.Println("delete:", string(kvpair.Key), string(kvpair.Value))
}
}
// 删除目录下的所有key
delResp, err = kv.Delete(context.TODO(), "/cron/jobs/", clientv3.WithPrefix())
if err != nil {
fmt.Println(err)
return
}
// 删除从这个key开始的后面的两个key
delResp, err = kv.Delete(context.TODO(), "/cron/jobs/job1",clientv3.WithFromKey(), clientv3.WithLimit(2))
if err != nil {
fmt.Println(err)
return
}

 

5. watch操作

// 创建一个用于读写的kv
kv := clientv3.NewKV(client)
// 模拟etcd中kv的变化,每隔1s执行一次put-del操作
go func() {
for {
kv.Put(context.TODO(), "/cron/jobs/job7", "i am job7")
kv.Delete(context.TODO(), "/cron/jobs/job7")
time.Sleep(time.Second * 1)
}
}()
// 先get到当前的值,并监听后续变化
getResp, err := kv.Get(context.TODO(), "/cron/jobs/job7")
if err != nil {
fmt.Println(err)
return
}
// 现在key是存在的
if len(getResp.Kvs) != 0 {
fmt.Println("当前值:", string(getResp.Kvs[0].Value))
}
// 监听的revision起点
watchStartRevision := getResp.Header.Revision + 1
// 创建一个watcher
watcher := clientv3.NewWatcher(client)
// 启动监听
fmt.Println("从这个版本开始监听:", watchStartRevision)
// 设置5s的watch时间
ctx, cancelFunc := context.WithCancel(context.TODO())
time.AfterFunc(5*time.Second, func() {
cancelFunc()
})
watchRespChan := watcher.Watch(ctx, "/cron/jobs/job7", clientv3.WithRev(watchStartRevision))
// 得到kv的变化事件,从chan中取值
for watchResp := range watchRespChan {
for _, event := range watchResp.Events { //.Events是一个切片
switch event.Type {
case mvccpb.PUT:
fmt.Println("修改为:", string(event.Kv.Value),
"revision:", event.Kv.CreateRevision, event.Kv.ModRevision)
case mvccpb.DELETE:
fmt.Println("删除了:", "revision:", event.Kv.ModRevision)
}
}
}

watch操作的逻辑也很简单,但是要注意确定从哪个版本开始监听,全部监听是没有意义的

 

6. lease

// 用于申请租约
lease := clientv3.NewLease(client)
// 申请一个10s的租约
leaseGrantResp, err := lease.Grant(context.TODO(), 10) //10s
if err != nil {
fmt.Println(err)
return
}
// 拿到租约的id
leaseID := leaseGrantResp.ID
// 自动续租
keepRespChan, err := lease.KeepAlive(context.TODO(), leaseID)
if err != nil {
fmt.Println(err)
return
}
// 处理续租应答的协程
go func() {
select {
case keepResp := <-keepRespChan:
if keepRespChan == nil {
fmt.Println("lease has expired")
goto END
} else {
// 每秒会续租一次
fmt.Println("收到自动续租应答", keepResp.ID)
}
}
END:
}()
// 用于读写etcd的键值对
kv := clientv3.NewKV(client)
// put一个key-value,关联租约,实现10s后过期
// 防止程序宕机
putResp, err := kv.Put(context.TODO(), "/cron/lock/job1", "",
clientv3.WithLease(leaseID))
if err != nil {
fmt.Println(err)
return
}
fmt.Println("put success", putResp.Header.Revision)
for {
getResp, err := kv.Get(context.TODO(), "/cron/lock/job1")
if err != nil {
fmt.Println(err)
return
}
if getResp.Count == 0 {
fmt.Println("key-value is expired")
return
} else {
fmt.Println(getResp.Kvs)
time.Sleep(2 * time.Second)
}
}

 

7. operator

operator和普通的put、get等方法类似,有点像mysql里面的prepare,又封装了一层,在实现etcd分布式锁的时候有一些帮助

kv := clientv3.NewKV(client)
// 创建putop
putOp := clientv3.OpPut("/cron/jobs/job7", "")
// 执行op
opResp, err := kv.Do(context.TODO(), putOp)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("写入的revision:", opResp.Put().Header.Revision)
// 创建getOp
getOp := clientv3.OpGet("/cron/jobs/job7")
// 执行op
getResp, err := kv.Do(context.TODO(), getOp)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("revision:", getResp.Get().Kvs[0].ModRevision)
fmt.Println("取到的值为:", getResp.Get().Kvs[0].Value)

 

posted @   aganippe  阅读(910)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示