少比比直接代碼(你可以理解為給key設置過期時間,但是比redis要強大的是它可以自動續(xù)租)
package main
import (
"context"
"fmt"
"go.etcd.io/etcd/clientv3"
"go.etcd.io/etcd/mvcc/mvccpb"
"time"
)
func main() {
var (
config clientv3.Config
client *clientv3.Client
err error
kv clientv3.KV
keepResp *clientv3.LeaseKeepAliveResponse
keepRespChan <-chan *clientv3.LeaseKeepAliveResponse
)
//創(chuàng)建租約
lease := clientv3.NewLease(client)
//判斷是否有問題
if leaseRes,err := lease.Grant(context.TODO(),10);err != nil {
fmt.Println(err)
return
} else {
//得到租約id
leaseId := leaseRes.ID
//定義一個上下文使得租約5秒過期
ctx,_:= context.WithTimeout(context.TODO(),5*time.Second)
//自動續(xù)租(底層會每次講租約信息扔到 <-chan *clientv3.LeaseKeepAliveResponse 這個管道中)
if keepRespChan,err = lease.KeepAlive(ctx,leaseId);err != nil {
fmt.Println(err)
return
}
//啟動一個新的協(xié)程來select這個管道
go func() {
for {
select {
case keepResp = <- keepRespChan:
if keepResp == nil {
fmt.Println("租約失效了")
goto END//失效跳出循環(huán)
} else {
//每秒收到一次應答
fmt.Println("收到租約應答",keepResp.ID)
}
}
}
END:
}()
//得到操作鍵值對的kv
kv = clientv3.NewKV(client)
//進行寫操作
if putResp,err = kv.Put(context.TODO(),"/cron/lock/job1","",clientv3.WithLease(leaseId)/*高速etcd這個key對應的租約*/);err != nil {
fmt.Println(err)
return
} else {
fmt.Println("寫入成功",putResp.Header.Revision/*這東西你可以理解為每次操作的id*/)
}
}
//監(jiān)聽這個key的租約是否過期
for {
if getResp,err = kv.Get(context.TODO(),"/cron/lock/job1");err != nil {
fmt.Println(err)
return
}
if getResp.Count == 0 {
fmt.Println("kv過期了")
break
}
fmt.Println("kv沒過期",getResp.Kvs)
time.Sleep(2 * time.Second)
}