日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

zookeeper分布式锁避免羊群效应(Herd Effect)

發(fā)布時(shí)間:2024/4/13 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 zookeeper分布式锁避免羊群效应(Herd Effect) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文主要講述在使用ZooKeeper進(jìn)行分布式鎖的實(shí)現(xiàn)過程中,如何有效的避免“羊群效應(yīng)(?herd effect)”的出現(xiàn)。

一般的分布式鎖實(shí)現(xiàn)

這里簡單的講下一般的分布式鎖如何實(shí)現(xiàn)。具體的代碼實(shí)現(xiàn)可以在這里看到:https://svn.apache.org/repos/asf/zookeeper/trunk/src/recipes/lock/

在之前的《ZooKeepe數(shù)據(jù)模型》一文中提到過,zookeeper中節(jié)點(diǎn)的創(chuàng)建類型有4類,這里我們重點(diǎn)關(guān)注下臨時(shí)順序節(jié)點(diǎn)。這種類型的節(jié)點(diǎn)有幾下幾個(gè)特性:

  • 節(jié)點(diǎn)的生命周期和客戶端會話綁定,即創(chuàng)建節(jié)點(diǎn)的客戶端會話一旦失效,那么這個(gè)節(jié)點(diǎn)也會被清除。
  • 每個(gè)父節(jié)點(diǎn)都會負(fù)責(zé)維護(hù)其子節(jié)點(diǎn)創(chuàng)建的先后順序,并且如果創(chuàng)建的是順序節(jié)點(diǎn)(SEQUENTIAL)的話,父節(jié)點(diǎn)會自動(dòng)為這個(gè)節(jié)點(diǎn)分配一個(gè)整形數(shù)值,以后綴的形式自動(dòng)追加到節(jié)點(diǎn)名中,作為這個(gè)節(jié)點(diǎn)最終的節(jié)點(diǎn)名。
  • 利用上面這兩個(gè)特性,我們來看下獲取實(shí)現(xiàn)分布式鎖的基本邏輯:

  • 客戶端調(diào)用create()方法創(chuàng)建名為“_locknode_/guid-lock-”的節(jié)點(diǎn),需要注意的是,這里節(jié)點(diǎn)的創(chuàng)建類型需要設(shè)置為EPHEMERAL_SEQUENTIAL。
  • 客戶端調(diào)用getChildren(“_locknode_”)方法來獲取所有已經(jīng)創(chuàng)建的子節(jié)點(diǎn),同時(shí)在這個(gè)節(jié)點(diǎn)上注冊上子節(jié)點(diǎn)變更通知的Watcher。
  • 客戶端獲取到所有子節(jié)點(diǎn)path之后,如果發(fā)現(xiàn)自己在步驟1中創(chuàng)建的節(jié)點(diǎn)是所有節(jié)點(diǎn)中序號最小的,那么就認(rèn)為這個(gè)客戶端獲得了鎖。
  • 如果在步驟3中發(fā)現(xiàn)自己并非是所有子節(jié)點(diǎn)中最小的,說明自己還沒有獲取到鎖,就開始等待,直到下次子節(jié)點(diǎn)變更通知的時(shí)候,再進(jìn)行子節(jié)點(diǎn)的獲取,判斷是否獲取鎖。
  • 釋放鎖的過程相對比較簡單,就是刪除自己創(chuàng)建的那個(gè)子節(jié)點(diǎn)即可。

    問題所在

    上面這個(gè)分布式鎖的實(shí)現(xiàn)中,大體能夠滿足了一般的分布式集群競爭鎖的需求。這里說的一般性場景是指集群規(guī)模不大,一般在10臺機(jī)器以內(nèi)。

    不過,細(xì)想上面的實(shí)現(xiàn)邏輯,我們很容易會發(fā)現(xiàn)一個(gè)問題,步驟4,“即獲取所有的子點(diǎn),判斷自己創(chuàng)建的節(jié)點(diǎn)是否已經(jīng)是序號最小的節(jié)點(diǎn)”,這個(gè)過程,在整個(gè)分布式鎖的競爭過程中,大量重復(fù)運(yùn)行,并且絕大多數(shù)的運(yùn)行結(jié)果都是判斷出自己并非是序號最小的節(jié)點(diǎn),從而繼續(xù)等待下一次通知——這個(gè)顯然看起來不怎么科學(xué)。客戶端無端的接受到過多的和自己不相關(guān)的事件通知,這如果在集群規(guī)模大的時(shí)候,會對Server造成很大的性能影響,并且如果一旦同一時(shí)間有多個(gè)節(jié)點(diǎn)的客戶端斷開連接,這個(gè)時(shí)候,服務(wù)器就會像其余客戶端發(fā)送大量的事件通知——這就是所謂的羊群效應(yīng)。而這個(gè)問題的根源在于,沒有找準(zhǔn)客戶端真正的關(guān)注點(diǎn)。

    我們再來回顧一下上面的分布式鎖競爭過程,它的核心邏輯在于:判斷自己是否是所有節(jié)點(diǎn)中序號最小的。于是,很容易可以聯(lián)想的到的是,每個(gè)節(jié)點(diǎn)的創(chuàng)建者只需要關(guān)注比自己序號小的那個(gè)節(jié)點(diǎn)。

    改進(jìn)后的分布式鎖實(shí)現(xiàn)

    下面是改進(jìn)后的分布式鎖實(shí)現(xiàn),和之前的實(shí)現(xiàn)方式唯一不同之處在于,這里設(shè)計(jì)成每個(gè)鎖競爭者,只需要關(guān)注”_locknode_”節(jié)點(diǎn)下序號比自己小的那個(gè)節(jié)點(diǎn)是否存在即可。實(shí)現(xiàn)如下:

  • 客戶端調(diào)用create()方法創(chuàng)建名為“_locknode_/guid-lock-”的節(jié)點(diǎn),需要注意的是,這里節(jié)點(diǎn)的創(chuàng)建類型需要設(shè)置為EPHEMERAL_SEQUENTIAL。
  • 客戶端調(diào)用getChildren(“_locknode_”)方法來獲取所有已經(jīng)創(chuàng)建的子節(jié)點(diǎn),注意,這里不注冊任何Watcher。
  • 客戶端獲取到所有子節(jié)點(diǎn)path之后,如果發(fā)現(xiàn)自己在步驟1中創(chuàng)建的節(jié)點(diǎn)序號最小,那么就認(rèn)為這個(gè)客戶端獲得了鎖。
  • 如果在步驟3中發(fā)現(xiàn)自己并非所有子節(jié)點(diǎn)中最小的,說明自己還沒有獲取到鎖。此時(shí)客戶端需要找到比自己小的那個(gè)節(jié)點(diǎn),然后對其調(diào)用exist()方法,同時(shí)注冊事件監(jiān)聽。
  • 之后當(dāng)這個(gè)被關(guān)注的節(jié)點(diǎn)被移除了,客戶端會收到相應(yīng)的通知。這個(gè)時(shí)候客戶端需要再次調(diào)用getChildren(“_locknode_”)方法來獲取所有已經(jīng)創(chuàng)建的子節(jié)點(diǎn),確保自己確實(shí)是最小的節(jié)點(diǎn)了,然后進(jìn)入步驟3。
  • 結(jié)論

    上次兩個(gè)分布鎖實(shí)現(xiàn),都是可行的。具體選擇哪個(gè),取決于你的集群規(guī)模。

    轉(zhuǎn)發(fā)來自:http://rdc.taobao.com/team/jm/archives/tag/zookeeper

    總結(jié)

    以上是生活随笔為你收集整理的zookeeper分布式锁避免羊群效应(Herd Effect)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。