Golang和Etcd的各种实现(分布式锁,队列等)

1,基本操作

package main

//etcd操作
import (
	"context"
	"fmt"
	"go.etcd.io/etcd/clientv3"
	"time"
)


func main() {
	cli,err := clientv3.New(clientv3.Config{
		Endpoints: []string{"127.0.0.1:2379"},
		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()
	ctx,cancel := context.WithTimeout(context.Background(),time.Second)
	_,err = cli.Put(ctx,"key","xiaoman")
	cancel()
	if err !=nil{
		fmt.Printf("put to etcd failed err :%v\n",err)
		return
	}
	ctx,cancel = context.WithTimeout(context.Background(),time.Second)
	resp,err := cli.Get(ctx,"key")
	cancel()
	if err !=nil{
		fmt.Printf("get from etcd failed ,err :%v\n",err)
		return
	}
	for _,ev := range resp.Kvs{
		fmt.Printf("%s:%s\n",ev.Key,ev.Value)
	}
}

  2,Etcd watch 可以动态获取配置文件的修改

package main

//etcd watch
import (
	"context"
	"go.etcd.io/etcd/clientv3"
	"time"
	"fmt"
)

func main() {
	cli,err := clientv3.New(clientv3.Config{
		Endpoints: []string{"127.0.0.1:2379"},
		DialTimeout: time.Second*5,
	})
	if err !=nil{
		fmt.Printf("connect to etcd failed err:%v\n",err)
		return
	}
	fmt.Println("connect to etcd success")
	defer cli.Close()
	//ctx,cancel := context.WithTimeout(context.Background(),time.Second)
	//defer cancel()
	//排一个哨兵,一直监视着key的变化 返回的是通道
	rch := cli.Watch(context.Background(),"xm")
	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)
		}
	}
}

  3,etcd 实现分布式锁

package main

import (
	"flag"
	"github.com/coreos/etcd/clientv3"
	"go.etcd.io/etcd/clientv3/concurrency"
	"log"
	"math/rand"
	"strings"
	"time"
)

var(
	addr = flag.String("addr","http://127.0.0.1:2379","etcd addresss")
	lockName = flag.String("name","my-test-lock","lock name")
)

func main() {
	flag.Parse()

	rand.Seed(time.Now().UnixNano())

	endpoints := strings.Split(*addr,",")
	cli,err:= clientv3.New(clientv3.Config{Endpoints: endpoints})
	if err !=nil{
		log.Fatal(err)
	}
	defer cli.Close()
	userLock(cli) //测试锁
}

func userLock(cli1 *clientv3.Client){
	//为锁生成session
	s1,err := concurrency.NewSession(cli1)
	if err !=nil{
		log.Fatal(err)
	}
	defer s1.Close()
	locker := concurrency.NewLocker(s1,*lockName)

//	请求锁
	log.Println("acquiring lock")
	locker.Lock()
	log.Println("acquired lock")

	time.Sleep(time.Duration(rand.Intn(30))*time.Second)
	locker.Unlock() //释放锁
	log.Println("released lock")
}

  4,etcd实现分布式读写锁

package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/clientv3/concurrency"
	recipe "github.com/coreos/etcd/contrib/recipes"
	"log"
	"math/rand"
	"os"
	"strings"
	"time"
)

//etcd 提供的读写锁,可以在分布式环境中的不同的节点使用

var(
	addr =flag.String("addr","http://127.0.0.1:2379","etcd addresss")
	lockName = flag.String("name","my-test-lock","lock name")
	action = flag.String("rw","w","r means acquiring reaad lock w means cquiring write lock")
)

func main() {
	flag.Parse()

	rand.Seed(time.Now().UnixNano())
	 endpoints := strings.Split(*addr,",")
	 cli,err := clientv3.New(clientv3.Config{Endpoints: endpoints})
	 if err !=nil{
	 	log.Fatal(err)
	 }
	 defer cli.Close()
	 s1 ,err := concurrency.NewSession(cli)
	 if err !=nil{
	 	log.Fatal(err)
	 }

	 m1 := recipe.NewRWMutex(s1,*lockName)

	consolescanner := bufio.NewScanner(os.Stdin)
	for consolescanner.Scan(){
		action := consolescanner.Text()
		switch action {
		case "w":
			testWriterLocker(m1)
		case "r":
			testReaderLocker(m1)
		default:
			fmt.Println("unknow action")


		}
	}
}

func testWriterLocker(m1 *recipe.RWMutex)  {
	log.Println("acquiring write lock")
	if err :=m1.Lock();err !=nil{
		log.Fatal(err)
	}
	log.Println("acquired write lock ")

	time.Sleep(time.Duration(rand.Intn(30))*time.Second)

	//释放锁
	if err := m1.Unlock();err!=nil{
		log.Fatal(err)
	}
	log.Println("released write lock")
}

func testReaderLocker(m1 *recipe.RWMutex)  {
	log.Println("acquiring read lock")
	if err := m1.RLock();err !=nil{
		log.Fatal(err)
	}
	log.Println("acquired read lock")

	time.Sleep(time.Duration(rand.Intn(30))*time.Second)

	//释放锁
	if err :=m1.RUnlock();err != nil{
		log.Fatal(err)
	}
	log.Println("released read lock")
}

  5,etcd实现分布式队列

package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	recipe "github.com/coreos/etcd/contrib/recipes"
	"log"
	"os"
	"strings"
)

//etcd 实现分布式队列

var(
	addr = flag.String("addr","http://127.0.0.1:2379","etcd address")
	queueName = flag.String("name","my-test-queue","queue name")
)

func main() {
	flag.Parse()

	endpoints := strings.Split(*addr,",")

	cli,err := clientv3.New(clientv3.Config{Endpoints: endpoints})
	if err !=nil{
		log.Fatal(err)
	}
	defer cli.Close()

	//创建获取队列
	q := recipe.NewQueue(cli,*queueName)

	//从命令行读取命令
	consol := bufio.NewScanner(os.Stdin)
	for consol.Scan(){
		action := consol.Text()
		items := strings.Split(action," ")
		switch items[0] {
		case "push":
			if len(items) !=2 {
				fmt.Println("must set value to push")
				continue
			}
			q.Enqueue(items[1]) //入队
		case "pop":
			v ,err := q.Dequeue()//出队
			if err !=nil{
				log.Fatal(err)
			}
			fmt.Println(v) //输出出队元素
		case "quit","exit":
			return
		default:
			fmt.Println("unknow action")
		}
	}

}

  6,etcd实现队列优先级

package main

import (
	"bufio"
	"flag"
	"fmt"
	recipe "github.com/coreos/etcd/contrib/recipes"
	"github.com/coreos/etcd/clientv3"
	"log"
	"os"
	"strconv"
	"strings"
)

//etcd 实现队列优先级

var(
	addr = flag.String("addr","http://127.0.0.1:2379","etcd addresses")
	queueName = flag.String("name","my-test-queue","queue name")
)

func main() {
	flag.Parse()

	endpoints := strings.Split(*addr,",")

	cli,err := clientv3.New(clientv3.Config{Endpoints: endpoints})

	if err !=nil{
		log.Fatal(err)
	}
	defer cli.Close()
	// 创建/获取队列
	q := recipe.NewPriorityQueue(cli,*queueName)

	consol := bufio.NewScanner(os.Stdin)
	for consol.Scan(){
		action := consol.Text()
		item := strings.Split(action," ")
		switch item[0] {
		case "push":
			if len(item) !=3{
				fmt.Println("must be value and priority to push")
				continue
			}
			pr,err := strconv.Atoi(item[2]) //读取优先级
			if err !=nil{
				fmt.Println("must set unit16 as priority")
				continue
			}
			q.Enqueue(item[1],uint16(pr))
		case "pop":
			v,err := q.Dequeue() //出队
			if err !=nil{
				log.Fatal(err)
			}
			fmt.Println(v)
		case "quit","exit":
			return
		default:
			fmt.Println("unknow action")
		}
	}
}

  7,etcd互斥锁

package main

import (
	"context"
	"flag"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/clientv3/concurrency"
	"log"
	"math/rand"
	"strings"
	"time"
)

//测试etcd的互斥锁
var(
	addr  = flag.String("addr","http://127.0.0.1:2379","etcd address")
	lockName = flag.String("name","my-test-lock","lock name")
)

func main() {
	flag.Parse()

	endpoints := strings.Split(*addr,",")
	cli,err := clientv3.New(clientv3.Config{Endpoints: endpoints})
	if err !=nil{
		fmt.Println("connect etcd failed err :",err)
		return
	}
	defer cli.Close()
	//useTestLock(cli) //locker
	//useMetux(cli) //mutex

	//RWLOCK
	

}

func useMetux(cli *clientv3.Client){
	rand.Seed(time.Now().UnixNano())
	s1,err:= concurrency.NewSession(cli)
	if err !=nil{
		log.Fatal(err)
	}
	defer s1.Close()

	m1 := concurrency.NewMutex(s1,*lockName)
	fmt.Printf("befor acquiring key:%s\n",m1.Key())

	log.Println("acquiring lock...")
	if err := m1.Lock(context.TODO());err !=nil{
		log.Fatal(err)
	}
	log.Println("acquired lock ...")
	log.Printf("acquired lock. key: %s", m1.Key())

	time.Sleep(time.Duration(rand.Intn(30))*time.Second)
	if err := m1.Unlock(context.TODO());err !=nil{
		log.Fatal(err)
	}
	log.Println("release lock...")
}

func useTestLock(cli *clientv3.Client)  {
	rand.Seed(time.Now().UnixNano())
	//为锁生成session
	s1,err := concurrency.NewSession(cli)
	if err !=nil{
		log.Fatal(err)
	}
	defer s1.Close()
	//得到一个分布式锁
	locker := concurrency.NewLocker(s1,*lockName)

	fmt.Println("acquiring lock...")
	locker.Lock()
	fmt.Println("acquired lock ...")

	time.Sleep(time.Duration(rand.Intn(30))*time.Second)
	locker.Unlock()
	fmt.Println("released lock..")
}

  

posted @ 2021-01-22 11:35  pebblecome  阅读(1615)  评论(0)    收藏  举报