package main
import (
"fmt"
"context"
"time"
"github.com/coreos/etcd/clientv3"
// "github.com/coreos/etcd/clientv3/concurrency"
"log"
)
func main(){
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"10.228.23.144:20004"},
DialTimeout: 5 * time.Second,
})
if err != nil {
fmt.Printf("connect to etcd Failed, err:%v\n",err)
return
}
fmt.Println("connect to etcd Success")
defer cli.Close()
// watch
// fmt.Println("on watch ...")
// rch := cli.Watch(context.Background(), "aaa")
// for wresp := range rch{
// for _,ev := range wresp.Events {
// fmt.Printf("Type: %s Key: %s Value: %s \n",ev.Type, ev.Kv.Key, ev.Kv.Value)
// }
// }
// lease
// fmt.Println("create lease put")
// resp, err := cli.Grant(context.TODO(), 10)
// if err != nil {
// fmt.Printf("create lease err: %v", err)
// }
// kkk, err := cli.Put(context.TODO(), "/zzz/", "wl", clientv3.WithLease(resp.ID))
// if err != nil{
// fmt.Printf("put lease err: %v", err)
// }
// fmt.Println("put result: ", kkk)
// keepalive
// fmt.Println("lease keepalive")
// ch, keer := cli.KeepAlive(context.TODO(), resp.ID)
// if keer != nil {
// fmt.Printf("keepalive lease err: %v", keer)
// }
// fmt.Println("keepalive lease ...")
// for {
// ka := <- ch
// fmt.Println("ttl:", ka.TTL)
// }
// 分布式锁
// // 创建两个单独的会话 锁竞争
// s1, err := concurrency.NewSession(cli)
// if err != nil{
// log.Fatal("s1 err: %v", err)
// }
// defer s1.Close()
// m1 := concurrency.NewMutex(s1, "/my_lock/")
// s2, err := concurrency.NewSession(cli)
// if err != nil{
// log.Fatal("s2 err: %v", err)
// }
// defer s2.Close()
// m2 := concurrency.NewMutex(s2, "/my_lock/")
// // 会话 s1 获取锁
// if err := m1.Lock(context.TODO()); err != nil{
// log.Fatal("s1 lock err: %v", err)
// }
// fmt.Println("acquired lock for s1")
// go func(){
// // 直到 s1 释放 /my_lock/ 锁
// if err := m2.Lock(context.TODO());err != nil{
// log.Fatal("s2 lock err: %v", err)
// }
// }()
// if err := m1.Unlock(context.TODO());err != nil {
// log.Fatal("m1 unlock err: %v", err)
// }
// fmt.Println("realeased lock for s1")
// fmt.Println("acquired lock for s2")
// // 带租约的分布式锁
// res, err := cli.Grant(context.Background(),20)
// if err != nil{
// log.Fatal(err)
// }
// fmt.Println("s1 wait lock...")
// // ss1, err := concurrency.NewSession(cli, concurrency.WithTTL(1))给创建的session一个1s的alive时期,即如果task1所在的进程挂掉,则ss1会被server在1s后关掉,这样task2就能立即获取成功锁
// // concurrency.WithContext(context.Background())使用该参数生成session会默认在task1所在的进程挂掉,则ss1会被server在60s后关掉,这样task2就能立即获取成功锁.
// // 所以若想让task2立即获取锁则应该使用
// // ss1, err := concurrency.NewSession(cli, concurrency.WithTTL(1))
// s1, err := concurrency.NewSession(cli, concurrency.WithLease(res.ID))
// if err != nil{
// log.Fatal(err)
// }
// m1 := concurrency.NewMutex(s1, "/kkk/")
// if err := m1.Lock(context.Background()); err != nil{
// log.Fatal(err)
// }
// fmt.Println("s1 get lock")
// s1.Orphan() // 直到租约到期,才释放锁
// fmt.Println("s2 wait lock...")
// s2, err := concurrency.NewSession(cli)
// if err != nil {
// log.Fatal(err)
// }
// m2 := concurrency.NewMutex(s2, "/kkk/")
// // 获取锁使用context.Background()会一直获取锁直到获取成功
// // 如果这里使用context.WithTimeout(context.Background(), 10*time.Second)
// // 表示获取锁10s如果没有获取成功则返回error。
// if err := m2.Lock(context.Background()); err != nil{
// log.Fatal(err)
// }
// fmt.Println("s2 get lock")
// PUT GET
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
put_r, err := cli.Put(ctx, "/abc/", "abc")
fmt.Println(put_r)
fmt.Println(cancel)
cancel()
if err != nil{
log.Fatal(err)
}
ctx, cancel = context.WithTimeout(context.Background(), time.Second)
resp, err := cli.Get(ctx, "/abc/")
cancel()
if err != nil{
log.Fatal(err)
}
for i, ev := range resp.Kvs{
fmt.Println(i,string(ev.Key),string(ev.Value))
}
/*
1. context包的WithTimeout()函数接受一个 Context 和超时时间作为参数,返回其子Context和取消函数cancel
2. 若不调用cancel函数,到了原先创建Contetx时的超时时间,它也会自动调用cancel()函数,即会往子Context的Done通道发送消息
*/
}
参考链接:https://www.topgoer.com/数据库操作/go操作etcd/操作etcd.html
参考链接:https://www.jianshu.com/p/aaefc8e1ffcb
参考链接:https://blog.csdn.net/yzf279533105/article/details/107292247