日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

从新冠疫情出发,漫谈 Gossip 协议

發布時間:2024/4/11 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从新冠疫情出发,漫谈 Gossip 协议 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

眾所周知周知,疫情仍然在全球各地肆虐。據最新數據統計,截至北京時間 2020-05-28,全球累計確診 5698703 例,累計死亡 352282 例,累計治愈 2415237 例。

從上面的統計數據,我們可以看出,新冠病毒在人與人之間的傳播是極其高效的,且影響范圍廣。如果我們把「新冠病毒」想象成一小段數據,將「人與人之間傳播」想象成數據交換,那么,我們可以得出結論,在不考慮免疫系統和人為干預等一些因素,經過反復迭代,數據(新冠病毒)可以被發送(感染)到每個節點(人)上。

這個就是今天要介紹的 Gossip 協議,該協議早在 1987 年就被發表在 ACM 上的論文《Epidemic Algorithms for Replicated Database Maintenance》中。當時主要用在分布式數據庫系統中各個副本節點間同步數據。

Gossip 協議簡介

Gossip 協議分為 Push-based 和 Pull-based 兩種模式,具體工作流程如下:

Push-based 的 Gossip 協議:

  • 網絡中的某個節點隨機選擇N個節點作為數據接收對象

  • 該節點向其選中的N個節點傳輸相應數據

  • 接收到數據的節點對數據進行存儲

  • 接收到數據的節點再從第一步開始周期性執行

Pull-based 的 Gossip 協議,正好相反:

  • 集群內的所有節點,隨機選擇其它 k 個節點詢問有沒有新數據

  • 接收到請求的節點,返回新數據

如何實現 Gossip

這邊簡單分析下 HashiCorp 公司的 Serf 的核心庫 Memberlist。這家公司研發了 Consul(基于 raft 實現的分布式存儲)、Vagrant(聲明式虛擬機編排)等優秀的產品。最近由于中美矛盾升級,也陷入到了輿論的漩渦中,爆出禁止在中國使用他們的產品的傳聞。不過,這是題外話。

Memberlist 這個 Golang 的代碼庫,基于 Gossip 協議,實現了集群內節點發現、 節點失效探測、節點故障轉移、節點狀態同步等。

其核心實現的大致如下:

  • newMemberlist():初始化 Memberlist 對象,根據配置監聽 TCP/UDP 端口,用于之后通信。這邊需要注意一點,雖然是基于 Gossip 協議實現的,但是并不是所有信息都采用 Gossip 進行數據交換。比如節點加入集群的時候,為了盡快的讓集群內所有節點感知到,采用遍歷當前已知的所有節點并通過 TCP 連接發送并接收數據的方式,來確保跟所有節點完成數據交換。

  • gossip():Memberlist 對象啟動之后,會定期使用 Gossip 協議,隨機選擇集群內的節點,采用 UDP 傳輸方式發送當前節點狀態以及用戶自定義的數據。

  • pushPull():還會定期隨機選擇一個節點,通過 TCP 傳輸方式與其做全量數據交換,加速集群內數據一致性收斂。

  • probe():還會定期輪訓集群內的一個節點,通過 UDP 方式發送心跳探測包,做到節點感知。

深入 Gossip 核心代碼

發送端處理流程:

  • 周期性地隨機選擇 m.config.GossipNodes 個節點,然后廣播正在等待發送的信息

// Create a gossip ticker if needed
if m.config.GossipInterval > 0 && m.config.GossipNodes > 0 {
t := time.NewTicker(m.config.GossipInterval)
go m.triggerFunc(m.config.GossipInterval, t.C, stopCh, m.gossip)
m.tickers = append(m.tickers, t)
}

// gossip is invoked every GossipInterval period to broadcast our gossip
// messages to a few random nodes.
func (m *Memberlist) gossip() {
defer metrics.MeasureSince([]string{“memberlist”, “gossip”}, time.Now())

// Get some random live, suspect, or recently dead nodes m.nodeLock.RLock() kNodes := kRandomNodes(m.config.GossipNodes, m.nodes, func(n *nodeState) bool {if n.Name == m.config.Name {return true}switch n.State {case StateAlive, StateSuspect:return falsecase StateDead:return time.Since(n.StateChange) > m.config.GossipToTheDeadTimedefault:return true} }) m.nodeLock.RUnlock()// ...for _, node := range kNodes {// Get any pending broadcastsmsgs := m.getBroadcasts(compoundOverhead, bytesAvail)if len(msgs) == 0 {return}addr := node.Address()if len(msgs) == 1 {// Send single message as isif err := m.rawSendMsgPacket(node.FullAddress(), &node.Node, msgs[0]); err != nil {m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", addr, err)}} else {// Otherwise create and send a compound messagecompound := makeCompoundMessage(msgs)if err := m.rawSendMsgPacket(node.FullAddress(), &node.Node, compound.Bytes()); err != nil {m.logger.Printf("[ERR] memberlist: Failed to send gossip to %s: %s", addr, err)}} }

}
接收端:

  • 接收數據報文,然后解析報文信息,并將信息記錄下來

// packetListen is a long running goroutine that pulls packets out of the
// transport and hands them off for processing.
func (m *Memberlist) packetListen() {
for {
select {
case packet := <-m.transport.PacketCh():
m.ingestPacket(packet.Buf, packet.From, packet.Timestamp)

case <-m.shutdownCh:return} }

}

func (m *Memberlist) ingestPacket(buf []byte, from net.Addr, timestamp time.Time) {
// …

// See if there's a checksum included to verify the contents of the message if len(buf) >= 5 && messageType(buf[0]) == hasCrcMsg {crc := crc32.ChecksumIEEE(buf[5:])expected := binary.BigEndian.Uint32(buf[1:5])if crc != expected {m.logger.Printf("[WARN] memberlist: Got invalid checksum for UDP packet: %x, %x", crc, expected)return}m.handleCommand(buf[5:], from, timestamp) } else {m.handleCommand(buf, from, timestamp) }

}

Gossip 協議的優缺點

看了 Memberlist 的實現,難免會有這樣的疑問,為什么要使用 Gossip 協議,直接在集群內廣播不香么?接下來,我們可以通過 Gossip 協議的優缺點來分析,使用 Gossip 協議的意義。

優點:

  • 協議簡單,實現起來很方便

  • 擴展性強,可以允許集群內節點任意增加或者減少,新增節點最終會與其他節點一致

  • 去中心化,節點之間是完全對等的

  • 最終一致性

缺點:

  • 數據同步延遲,因為只保證最終一致性,所以會出現某個時間點,部分節點數據不同步的情況

  • 傳輸數據冗余,相同數據在節點間會反復被傳輸

今天對 Gossip 的協議就簡單介紹到這里,如果有同學對內容感興趣,可以回復評論,我們私下多多探討和交流。

參考資料

https://en.wikipedia.org/wiki/Gossip_protocol

https://github.com/hashicorp/serf

https://github.com/hashicorp/memberlist

https://zhuanlan.zhihu.com/p/41228196

https://www.jianshu.com/p/de7b026f4997

總結

以上是生活随笔為你收集整理的从新冠疫情出发,漫谈 Gossip 协议的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。