<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] > [參考](https://chai2010.cn/advanced-go-programming-book/ch6-cloud/ch6-02-lock.html) ## 概述 與單機并發下需要加鎖一樣,在分布式場景下,我們也需要這種“搶占”的邏輯 ## 基于Redis的setnx 我們可以使用Redis提供的`setnx`命令(只有在 key 不存在時設置 key 的值) ``` package main import ( "fmt" "sync" "time" "github.com/go-redis/redis" ) func incr() { client := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB }) var lockKey = "counter_lock" var counterKey = "counter" // lock resp := client.SetNX(lockKey, 1, time.Second*5) lockSuccess, err := resp.Result() if err != nil || !lockSuccess { fmt.Println(err, "lock result: ", lockSuccess) return } // counter ++ getResp := client.Get(counterKey) cntValue, err := getResp.Int64() if err == nil || err == redis.Nil { cntValue++ resp := client.Set(counterKey, cntValue, 0) _, err := resp.Result() if err != nil { // log err println("set value error!") } } println("current counter is ", cntValue) delResp := client.Del(lockKey) unlockSuccess, err := delResp.Result() if err == nil && unlockSuccess > 0 { println("unlock success!") } else { println("unlock failed", err) } } func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() incr() }() } wg.Wait() } ``` 看看運行結果: ``` ??? go run redis_setnx.go <nil> lock result: false <nil> lock result: false <nil> lock result: false <nil> lock result: false <nil> lock result: false <nil> lock result: false <nil> lock result: false <nil> lock result: false <nil> lock result: false current counter is 2028 unlock success! ``` ## 基于ZooKeeper ``` package main import ( "time" "github.com/samuel/go-zookeeper/zk" ) func main() { c, _, err := zk.Connect([]string{"127.0.0.1"}, time.Second) //*10) if err != nil { panic(err) } l := zk.NewLock(c, "/lock", zk.WorldACL(zk.PermAll)) err = l.Lock() if err != nil { panic(err) } println("lock succ, do your business logic") time.Sleep(time.Second * 10) // do some thing l.Unlock() println("unlock succ, finish business logic") } ``` - 基于ZooKeeper的鎖與基于Redis的鎖的不同之處在于Lock成功之前會一直阻塞,這與我們單機場景中的`mutex.Lock`很相似 - 其原理也是基于臨時Sequence節點和watch API,例如我們這里使用的是`/lock`節點。Lock會在該節點下的節點列表中插入自己的值,只要節點下的子節點發生變化,就會通知所有watch該節點的程序。這時候程序會檢查當前節點下最小的子節點的id是否與自己的一致。如果一致,說明加鎖成功了 - 這種分布式的阻塞鎖比較適合分布式任務調度場景,但不適合高頻次持鎖時間短的搶鎖場景 ## 基于etcd ``` package main import ( "log" "github.com/zieckey/etcdsync" ) func main() { m, err := etcdsync.New("/lock", 10, []string{"http://127.0.0.1:2379"}) if m == nil || err != nil { log.Printf("etcdsync.New failed") return } err = m.Lock() if err != nil { log.Printf("etcdsync.Lock failed") return } log.Printf("etcdsync.Lock OK") log.Printf("Get the lock. Do something here.") err = m.Unlock() if err != nil { log.Printf("etcdsync.Unlock failed") } else { log.Printf("etcdsync.Unlock OK") } } ``` 1. 先檢查`/lock`路徑下是否有值,如果有值,說明鎖已經被別人搶了 2. 如果沒有值,那么寫入自己的值。寫入成功返回,說明加鎖成功。寫入時如果節點被其它節點寫入過了,那么會導致加鎖失敗,這時候到 3 3. watch`/lock`下的事件,此時陷入阻塞 4. 當`/lock`路徑下發生事件時,當前進程被喚醒。檢查發生的事件是否是刪除事件(說明鎖被持有者主動unlock),或者過期事件(說明鎖過期失效)。如果是的話,那么回到 1,走搶鎖流程。 值得一提的是,在**etcdv3**的API中官方已經提供了可以直接使用的**鎖API**,讀者可以查閱etcd的文檔做進一步的學習。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看