啥是Gossip協議?

why技術發表於2022-01-04

你好呀,我是歪歪。

元旦的時候我看到一個特別離譜的謠言啊,具體是什麼內容我就不說了,我怕髒了大家的眼睛。

但是,我看到一個群裡傳的那叫一個繪聲繪色,大家討論的風生水起的,彷彿大家就在現場似的。

這事吧本來我呵呵一笑也就過了。但是隔了一會我突然大腿一拍:這是個素材啊。

我可以和大家聊一個共識演算法呀。

說到共識演算法,大家首先想到的應該都是 Raft、Paxos、Zab 演算法這類理解起來比較困難的強一致性演算法。

但是還有一個弱一致性的共識演算法比較好理解,Gossip 協議。

Gossip,先看這個單詞,圈起來,要考的啊,這是一個六級詞彙,也是考研單詞,意思是“流言蜚語”。

接下來就帶你簡單的看看這個“流言蜚語”到底是怎麼回事。

Gossip 協議

Gossip 協議最早提出的時間得追溯到 1987 年釋出的一篇論文:《Epidemic Algorithms for Replicated Database Maintenance》

http://bitsavers.trailing-edge.com/pdf/xerox/parc/techReports/CSL-89-1_Epidemic_Algorithms_for_Replicated_Database_Maintenance.pdf

我第一次看到這個論文的名字的時候,我都懵逼了:這也沒有 Gossip 的關鍵詞呢。

主要是 Epidemic Algorithms 這兩個單詞,我又恰好認識。

Algorithms,演算法,沒啥說的。

Epidemic 是啥?

緊扣當下時事:

所以 Epidemic Algorithms 翻譯過來就是流行病演算法。

因此 Gossip 的學名應該是又叫做“流行病演算法”,只是大家更喜歡叫它 Gossip 而已。畢竟,雖不喜歡聽點兒“小道訊息”呢?

說論文之前,先簡單定個基調。

你覺得一致性協議最基礎、最核心、最重要的一個動作是什麼?

是不是資料更新?

為了保證各個節點的資料的一致性,必然就涉及到資料的更新操作。

所以,在論文的開篇介紹部分描述了三種方法來進行資料的更新:

  • Direct mail(直接郵件)
  • Anti-entropy(反熵)
  • Rumor mongering(傳謠)

Direct mail(直接郵寄)

廢話先不說了,直接上個圖:

上面這圖啥意思呢?

就是一共八個小圓點,假設每個都代表一個伺服器,它們之間都是平等的關係,不存在中心節點、主從什麼的關係。

其中最上面的紅色節點表示該節點有資料變更了,於是把變更的資料直接通知給剩下的節點。

如果其他的節點上發生了資料變更也是同樣的道理。

可以簡單的理解為一個迴圈遍歷,每發生一次資料變更,為了保持資料的一致性,就得進行一次迴圈遍歷。

這個方案的優點很明顯:簡單、粗暴、直接。

但是缺點和優點一樣明顯,我們看看論文裡面怎麼說:

主要看 but 的部分:

首先不完全可靠,因為這個要求每個站點都必須知道所有站點的存在。但是實際情況是有的站點並不總是知道所有其他站點。

然後,資訊(mail)有時會丟失,一旦丟失,就連最終一致性也保證不了,整個涼涼。

其實 Direct mail(直接郵寄)並不是論文裡面主要討論的方案,把它寫在第一個起一個拋磚引玉的作用。

主要聊聊 Anti-entropy(反熵)和 Rumor-Mongering(傳謠)這兩個方案。

先定個整體的基調:

  • Anti-entropy(反熵),是傳播節點上的所有的資料
  • Rumor-Mongering(傳謠),是傳播節點上的新到達的、或者變更的資料

說白了,一個是全量,一個是增量。

Anti-entropy(反熵)

部分同學可能對“反熵”這個詞感到莫名其妙哈,其實主要是不瞭解啥是“熵”。

其實說白了,“熵”的通俗理解就是“混亂程度”。

比如你的房間,如果你不去整理那麼各自物品的擺放就會越來越混亂,也就是越來越“熵”。而你整理房間的這個操作就是“反熵”。

這個東西你可以簡單的先這樣理解,我一時半會也給你說不清楚,這東西要聊下去的話得上升到宇宙和哲學的高度。

我主要怕你聽不懂。

在論文裡面是這樣的描述 Anti-entropy 模式的:

每個伺服器有規律地隨機選擇另一個伺服器,這二者通過交換各自的內容來抹平它們之間的所有差異,這種方案是非常可靠的。

(but 開始了)但需要檢查各自伺服器的全量內容,言外之意就是資料量略大,因此不能使用太頻繁。

實驗表明,反熵雖然可靠,但傳播更新的速度比直接郵件慢得多。

如果不同步,那麼兩者之間的資料差異越來越大,也就是越來越熵。

同步的目的是縮小差異,達到最終一致性,這就是反熵。

定義就是這麼個定義。

Rumor mongering(傳謠)

比起反熵,傳謠從字面上就很好理解了。

比如我是一個大學生,並不能完全認識整個學校的人。但是學校裡面的同學之間都有千絲萬縷的聯絡。

假設有一天,我剛好碰見校花一個人走在路上,我就上去和她討論了一下計算機領域裡面的共識演算法等相關問題,關於這些問題我們進行了深入的討論並且交換了彼此的理解和看法。

我們這邊就是說,整個過程是越討論越激烈,不知道怎麼走著走著就走到了情人坡。

應該每個大學都有一個叫做情人坡的地方吧。

然後被別的妹子看見了。她就給她閨蜜說:你知道歪歪嗎?對,就是大一新生,那個大帥比。我那會看到他和校花在情人坡那邊溜達。

然後一傳十、十傳百。這個訊息全校師生都知道了。

“歪歪和校花在情人坡那邊溜達”這個訊息就通過 gossip 的傳謠模式,達到了最終一致性。

“傳謠”和“反熵”的差別在於只傳遞新資訊或者發生了變更的資訊,而不需要傳遞全量的資訊。

比如上面的這個例子中,只需要同步“歪歪和校花在情人坡那邊溜達”這個最新的訊息就行。

而不需要同步“歪歪是誰,校花是誰,情人坡在哪”等等這些之前大家早就達成一致性的資訊。

在提到“傳謠”和“反熵”的時候,論文中還有這麼個定義:

simple epidemics:單純性傳染病

在這種模式下,包含兩種狀態:infective(傳染性) 和 susceptible(易感染)。

處於 infective 狀態的節點代表其有資料更新,需要把資料分享(傳染)給其他的節點。

處於 susceptible 狀態的節點代表它還沒接受到其他節點的資料更新(沒有被感染)。

所以,後面我提到“感染”的時候,你應該要知道我是從這裡看到的,不是胡編的。

關於“傳謠”和“反熵”,再借用周志明老師《鳳凰架構》裡面的正經一點的描述,是這樣的:

http://icyfenix.cn/distribution/consensus/gossip.html

達到一致性耗費的時間與網路傳播中訊息冗餘量這兩個缺點存在一定對立,如果要改善其中一個,就會惡化另外一個。

由此,Gossip 設計了兩種可能的訊息傳播模式:反熵(Anti-Entropy)和傳謠(Rumor-Mongering),這兩個名字都挺文藝的。

熵(Entropy)是生活中少見但科學中很常用的概念,它代表著事物的混亂程度。

反熵的意思就是反混亂,以提升網路各個節點之間的相似度為目標,所以在反熵模式下,會同步節點的全部資料,以消除各節點之間的差異,目標是整個網路各節點完全的一致。

但是,在節點本身就會發生變動的前提下,這個目標將使得整個網路中訊息的數量非常龐大,給網路帶來巨大的傳輸開銷。

而傳謠模式是以傳播訊息為目標,僅僅傳送新到達節點的資料,即只對外傳送變更資訊,這樣訊息資料量將顯著縮減,網路開銷也相對較小。

一個網站

攤牌了,其實我是看到了這個網站,才決定寫這篇文章的。

因為這個網站裡面直接有非常模擬的動畫模擬 gossip 協議的同步過程,一個動圖勝過千言萬語。

地址先放在這裡,大家可以自己訪問玩兒一下:

https://flopezluis.github.io/gossip-simulator/

先給你看一眼它的工作過程:

甭管看沒看懂吧,這玩意至少看起來很厲害的樣子。

接下來就給你介紹一下它是怎麼玩的:

首先我們看這裡的 Nodes 和 Fanout。

Nodes 其實很好理解,就是節點數,這裡的 40 就代表下面的小圓圈的個數,比如我今年 18 歲,那麼我把它改成 18 它就是這樣的:

主要是這個 Fanout 是個啥玩意呢?

在這個網頁的頭部的輪播圖裡面,第一張圖是這樣的:

答案就藏在這個 Learn more 裡面。

https://managementfromscratch.wordpress.com/2016/04/01/introduction-to-gossip/

這段話裡面就解釋了,什麼是 Fanout。同時也簡單的介紹了 gossip 協議的基本工作原理。

它說 gossip 協議在概念上非常簡單,編碼也非常簡單。它們背後的基本想法是這樣的:

一個節點想與網路中的其他節點分享一些資訊。然後,它定期從節點集合中隨機選擇一個節點並交換資訊,收到資訊的節點也做同樣的事情。
該資訊定期傳送到 N 個目標,N 被稱為扇出(Fanout)。

所以,前面的 Fanout=4,含義就是某個節點,每次會把自己想要分享的資訊同步給叢集中的另外 4 個節點。

在模擬器中體現出來應該是這樣的:

上面這個圖你可以看到有很多線,但是它們的起點都是一個紅色的節點。

這個紅色的節點就是你用滑鼠隨意點選小圓圈中的一個或者多個都可以,滑鼠一點選就會變成紅色,就是完犢子了,紅碼了,表示“被感染”了。

上面的線條是怎麼搞出來的呢?

有了一個紅色的小圓圈之後,點選上面的“Show Paths”就會出現路徑了:

但是不是說好 Fanout=4 嗎,為什麼怎麼多的路徑?

因為,雖然這個節點知道這麼多其他節點,但是它只會選擇其中的 4 個進行感染。

上面這個圖還是有點複雜,所以我把引數都調小一點,這樣看起來就清爽多了:

叢集中有一個節點的資訊更新了,這個節點知道其他 5 個節點的存在,但是它只會把資訊推送給其中的兩個,點選 Send Message 按鈕之後就會像是這樣:

你可以發現上面這個圖裡面已經有三個紅色的節點了,有兩條路徑變粗了,含義是從這個路徑傳播過來的。

整個叢集最終會全部完成“感染”,達成最終一致性:

同時,gossip 協議它也具備容錯性:

按照頁面上的提示,我們是可以通過 “Delete” 按鈕刪除一部分路徑的,比如下面這樣:

刪除兩個路徑,代表這幾個節點之間是不可達的,但是最終這個叢集還是會全部被感染。

再來個動圖演示一下,可以看到路徑刪除後,這個節點再也不會給對應的節點通訊,但是整個叢集還是達到了收斂:

你自己也可以開啟網站去玩一下,還有一個小技巧是這樣的:

點選 Play 按鈕,是可以隨時暫停的,這樣就更容易觀察到整個傳播的過程。

最後,關於這個圖裡面,還有一個關鍵的東西沒有說,就是裡面的這個公式:

在 Learn More 裡面也有提到這個公式,其實它就是 gossip 協議的複雜度,O(logN) :

比如,每次都設定為 Fanout=4,那麼節點數和預估傳播輪次之間的關係是這樣的:

  • 40 個節點,2.66 輪
  • 80 個節點,3.16 輪
  • 160 個節點,3.66 輪
  • 320 個節點,4.16 輪
  • 640 個節點,4.66 輪
  • ...

可以看到,隨著節點數的翻倍增加,傳播輪次並沒有明顯的增加。

這就是前面 Learn More 截圖裡面提到的這個詞:Scalable

這是個四級詞彙啊,會考的,記住了,是“可伸縮”的意思。

採用 gossip 協議的叢集,Scalable is very 的 nice。

其他注意點

在這個網站上,最重要的就是它的動圖模擬功能了,但是也不要忽略了它裡面的其他部分的描述。

比如這一段話,我就覺得非常的重要。

這一段話裡面提到了兩個問題,我一個個的說。

首先它說在網站模擬的過程中,所有節點傳送訊息似乎都是同步的,就像有一個全域性迴圈一樣。

在模擬中這樣做,是因為這樣看起來更加的直觀。

但是,在一個真正的 gossip 協議中,每個節點都有自己的週期,它們之間根本沒有也不需要同步。

上面是說什麼意思呢?

我再說的直白一點,每個節點往外同步訊息的時候,是按照自己的週期來處理的,比如每 10 秒一次。根本就不關心其他節點什麼時候觸發同步訊息的操作,只需要管好自己就行了。

第二問題我認為就很重要了:

How do the nodes know about each other?

節點之間怎麼知道其他節點的存在的?

其中一個方式就是當節點加入叢集時,必須知道該叢集中的一個節點的資訊。通過前面的動圖我們知道,如果一個節點被另外一個節點知道,那麼它最終也一定會被感染。

那問題就來了:新節點加入時又是如何知道叢集中一個節點資訊的呢?

很簡單,我知道的一個方案就是人工指定。

Redis 叢集採用的就是 gossip 協議來交換資訊。當有新節點要加入到叢集的時候,需要用到一個 meet 命令。

http://www.redis.cn/commands/cluster-meet.html

這玩意就是人工指定。

還有一個可以注意一下的是這個:

這裡提到了另外一個模擬的網站:

https://www.serf.io/docs/internals/simulator.html

它可以通過控制這幾個引數,來測算叢集達成一致性的時間。

上面這個圖表示的就是在資訊交換頻率(GOSSIP INTERVAL)為 0.2s,Fanout 節點數為 3,總節點數為 30,丟包率和節點失敗率為 0 的這個情況。

在這個情況下,對應的到達最終一致性的時間圖長這樣:

基本上在一秒的時間就搞定了。

你也可以自己去修改一下引數,看看對應的時間圖的變化。

比如,我只修改節點數,把它從 30 修改為 3000,時間圖變成了這樣:

在 1.75s 左右完成了收斂。

節點擴大 100 倍,但是時間增加不到 1s,確實是很優秀。

這玩意好是好,但是給你看個刺激的,來感受一下這恐怖的傳播規模:

從動圖中可以看出,前面一兩次傳播還好,至少眼睛還能看出個大概,但是到了後幾輪,大多數節點都被感染了,但是還在繼續對外傳播訊息。

這訊息數量,簡直是看的讓人頭皮發麻。

六度分隔理論

最後再說一個有意思的東西,叫做“六度分隔理論”:

1967年,哈佛大學的心理學教授Stanley Milgram想要描繪一個連結人與社群的人際連繫網。做過一次連鎖信實驗,結果發現了“六度分隔”現象。簡單地說:“你和任何一個陌生人之間所間隔的人不會超過六個,也就是說,最多通過六個人你就能夠認識任何一個陌生人。

六度分割理論,也叫小世界理論。這其實和 Gossip 協議也有千絲萬縷的聯絡。

我在小破站上看到一個相關的視訊,我覺得解釋的還是挺清楚的,你如果有興趣的話可以去看看:

https://www.bilibili.com/video/BV1b7411B7D2?t=31

在視訊裡面,有這樣的一個畫面:

好傢伙,這不是我們前面的網站上面的翻版嘛,看起來可太親切了。

這個理論剛剛提出來的時候還是“最多通過六個人你就能夠認識任何一個陌生人”。

但是隨著這幾年社交網路的急速發展,地球都被拉小到了一個“村”的概念了。

所以這個數字在逐漸的減少:

而且如果把這個範圍拉小一點,比如侷限在程式設計師這個小範圍內,那就更小了。

有時候拉個業務對接群,進去一看好傢伙還有前同事,你說這個圈子能有多大。

本文已收錄到個人部落格,歡迎大家來玩。

https://www.whywhy.vip/

相關文章