Geek

博客园 首页 新随笔 联系 订阅 管理

golang etcd 操作


go get -u -x google.golang.org/grpc@v1.26.0


package main

import (
	"context"
	"fmt"
	"time"

	"github.com/coreos/etcd/clientv3"
)

func main() {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"localhost:2379"},
		DialTimeout: time.Duration(5) * time.Second,
	})

	if err != nil {
		fmt.Println("connect failed, err", err)
		return
	}

	fmt.Println("connect success")
	defer cli.Close()

	for {
		ctx, cancel := context.WithCancel(context.Background())
		fmt.Println("Please input xi value:")
		var xiValue string
		fmt.Scanln(&xiValue)

		// 如果输入exit,退出程序
		if xiValue == "exit" {
			break
		}

		_, err = cli.Put(ctx, "/xi", xiValue)
		cancel()
		if err != nil {
			fmt.Println("put failed, err: ", err)
			return
		}

		ctx, cancel = context.WithCancel(context.Background())
		resp, err := cli.Get(ctx, "/xi")
		cancel()

		if err != nil {
			fmt.Println("get failed, err: ", err)
			return
		}
		for _, ev := range resp.Kvs {
			fmt.Printf("%s, %s\n", ev.Key, ev.Value)
		}
	}
}


etcd 实现分布式锁

package example

import (
	"context"
	"fmt"
	"sync"
	"testing"

	"github.com/coreos/etcd/clientv3"
)

var (
	cnt int
	// expect int
)

func worker(i int) int {
	cnt++
	return 1
}

type XLock struct {
	lease      clientv3.Lease
	kv         clientv3.KV
	LockKey    string
	cancelFunc context.CancelFunc
}

func New(cli *clientv3.Client) *XLock {
	return &XLock{
		lease:   clientv3.NewLease(cli),
		kv:      clientv3.NewKV(cli),
		LockKey: "simple0",

		// cancelFunc: context.CancelFunc,
	}
}
func (u *XLock) LockTest0() (err error) {
	var (
		leaseGrantResp *clientv3.LeaseGrantResponse
		cancelCtx      context.Context
		cancelFunc     context.CancelFunc
		leaseid        clientv3.LeaseID
		keepRespChan   <-chan *clientv3.LeaseKeepAliveResponse
	)
	if leaseGrantResp, err = u.lease.Grant(context.TODO(), 5); err != nil {
		return
	}
	leaseid = leaseGrantResp.ID
	// 释放租约
	defer u.lease.Revoke(context.TODO(), leaseid)
	cancelCtx, cancelFunc = context.WithCancel(context.TODO())
	defer cancelFunc()

	if keepRespChan, err = u.lease.KeepAlive(cancelCtx, leaseid); err != nil {
		// goto FAIL
		return err
	}
	_ = keepRespChan
	go func() {
		var (
			keepResp *clientv3.LeaseKeepAliveResponse
		)
		for {
			select {
			case keepResp = <-keepRespChan:
				if keepResp == nil {
					goto END
				}
			}
		}
	END:
	}()
	// 创建 etcd 事务
	txn := u.kv.Txn(context.TODO())
	lockkey := u.LockKey
	txn.If(clientv3.Compare(clientv3.CreateRevision(lockkey), "=", 0)).Then(clientv3.OpPut(lockkey, "", clientv3.WithLease(leaseid))).
		Else(clientv3.OpGet(lockkey))
	// 提交事务
	var (
		txnResp *clientv3.TxnResponse
	)

	if txnResp, err = txn.Commit(); err != nil {
		return err
	}
	if !txnResp.Succeeded {
		fmt.Println("版本更新了!")
		// return fmt.Errorf("失败更新")
	}

	fmt.Println("dot it")

	cnt++
	// return fmt.Errorf("error 0 %w", err)
	return nil
}

func Test_llock(t *testing.T) {

	if client, err = clientv3.New(conf); err != nil {
		t.Log(err)
		return
	}
	maxn := 50
	var wg sync.WaitGroup
	for i := 0; i < maxn; i++ {
		wg.Add(1)
		go func() {
			ll := New(client)
			ll.LockTest0()
			wg.Done()
		}()
	}
	wg.Wait()
	if cnt != maxn {
		t.Errorf("errror cnt=%d, want %d", cnt, maxn)
	} else {
		t.Logf("succeess cnt=%d, want %d", cnt, maxn)
	}

}



posted on 2022-11-16 11:11  .geek  阅读(184)  评论(0编辑  收藏  举报