etcd实现分布式锁

分布式锁在后台应用广泛,抢票系统,秒杀系统都能看到它的身影,实现分布式锁的方式有很多,比如zookeeper,redis,以及etcd。下面用一个简单的用例来说明etcd的实现。

package main

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

func main() {
    cli,err := clientv3.New(clientv3.Config{
        Endpoints:            []string{"localhost:12379", "localhost:22379", "localhost:32379"},
        AutoSyncInterval:     0,
        DialTimeout:          5 * time.Second,
        DialKeepAliveTime:    0,
        DialKeepAliveTimeout: 0,
        MaxCallSendMsgSize:   0,
        MaxCallRecvMsgSize:   0,
        TLS:                  nil,
        Username:             "",
        Password:             "",
        RejectOldCluster:     false,
        DialOptions:          nil,
        Context:              nil,
    })
    if err != nil{
        log.Fatal("err:",err.Error())
    }
    // 创建两个单独的会话用来演示锁竞争
    s1,err := concurrency.NewSession(cli)
    if err != nil{
        log.Fatal(err)
    }
    defer s1.Close()
    m1 := concurrency.NewMutex(s1,"/my-lock/")

    s2,err := concurrency.NewSession(cli)
    if err != nil{
        log.Fatal(err)
    }
    defer s2.Close()
    m2 := concurrency.NewMutex(s2,"/my-lock/")

    // 会话s1获取锁
    if err := m1.Lock(context.TODO());err != nil{
        log.Fatal(err)
    }
    m2Locked := make(chan struct{})
    go func() {
        defer close(m2Locked)
        // 等待直到会话s1释放了/my-lock/的锁
        if err := m2.Lock(context.TODO());err != nil{
            log.Fatal(err)
        }
        fmt.Println("m2 locked")
    }()

    if err := m1.Unlock(context.TODO());err != nil{
        log.Fatal(err)
    }
    fmt.Println("released lock for s1")
     <- m2Locked
     fmt.Println("acquired lock for s2")
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。