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..")
}

浙公网安备 33010602011771号