1. 程式人生 > >Cassandra學習筆記之Gossip協議

Cassandra學習筆記之Gossip協議

Gossip協議概述

Cassandra叢集中的節點沒有主次之分,它們通過一種叫做Gossip的協議進行通訊。通過Gossip協議,它們可以知道叢集中有哪些節點,以及這些節點的狀態如何?每一條Gossip訊息上都有一個版本號,節點可以對接收到的訊息進行版本比對,從而得知哪些訊息是我需要更新的,哪些訊息是我有而別人沒有的,然後互相傾訴吐槽,確保二者得到的資訊相同,這很像現實生活中的八卦(擺龍門陣)一樣,一傳十,十傳百,最後盡人皆知。 在Cassandra啟動時,會啟動Gossip服務,Gossip服務啟動後會啟動一個任務GossipTask,這個任務會週期性地與其他節點進行通訊。GossipTask是位於org.apache.cassandra.gms.Gossip類下的一個內部類,其run方法如下:
public void run(){
      MessagingService.instance().waitUntilListening();

      /* Update the local heartbeat counter. */
      endpointStateMap.get(FBUtilities.getBroadcastAddress()).getHeartBeatState().updateHeartBeat();

      final List<GossipDigest> gDigests = new ArrayList<GossipDigest>();
      Gossiper.instance.makeRandomGossipDigest(gDigests);

      if (gDigests.size() > 0){
          GossipDigestSyn digestSynMessage = new GossipDigestSyn(DatabaseDescriptor.getClusterName(),
                                                                 DatabaseDescriptor.getPartitionerName(),
                                                                 gDigests);
          MessageOut<GossipDigestSyn> message = new MessageOut<GossipDigestSyn>(MessagingService.Verb.GOSSIP_DIGEST_SYN,
                                                                                digestSynMessage,
                                                                                GossipDigestSyn.serializer);
          /* Gossip to some random live member */
          boolean gossipedToSeed = doGossipToLiveMember(message);

          /* Gossip to some unreachable member with some probability to check if he is back up */
          doGossipToUnreachableMember(message);

          if (!gossipedToSeed || liveEndpoints.size() < seeds.size())
              doGossipToSeed(message);

          doStatusCheck();
      }
}
主要做了幾下幾件事: 1、GossipTask在Gossip啟動後並不會立即執行,阻塞在listenGate這個條件變數上,當Gossip服務呼叫listen時才開始執行; 2、首先更新本節點的心跳版本號,然後構造需要傳送給其他節點的訊息gDigests; 3、從存活節點中隨機選擇一個節點發送、從失效節點中隨機選取一個傳送。如果當前存活節點數小於種子數,向其中一個種子節點發訊息; 4、檢查節點狀態。 有關種子節點和節點狀態後面再分析,本節只關注Gossip協議本身。 GossipTask用於向其他節點發送Gossip資訊,Cassandra還提供了SocketThread這樣一個執行緒來負責接收訊息,接收訊息的程式碼在org.apache.cassandra.net.IncomingTcpConnection類中。不管是傳送還是接收Gossip訊息,都是呼叫org.apache.cassandra.net.MessagingService的sendOneWay方法實現的。 一次Gossip通訊分為三個階段,如圖所示:

每個階段對應一個訊息類,這三個訊息類都有對應的處理器,處理器的註冊是在org.apache.cassandra.service.StorageService類中完成的,參考如下程式碼:
        MessagingService.instance().registerVerbHandlers(MessagingService.Verb.GOSSIP_DIGEST_SYN, new GossipDigestSynVerbHandler());
        MessagingService.instance().registerVerbHandlers(MessagingService.Verb.GOSSIP_DIGEST_ACK, new GossipDigestAckVerbHandler());
        MessagingService.instance().registerVerbHandlers(MessagingService.Verb.GOSSIP_DIGEST_ACK2, new GossipDigestAck2VerbHandler());
可見這三種訊息分別對應三個訊息型別GOSSIP_DIGEST_SYN、GOSSIP_DIGEST_ACK、GOSSIP_DIGEST_ACK2.
下面詳細分析每個階段。

GossipDigestSynMessage

GossipTask的run方法中傳送了GOSSIP_DIGEST_SYN型別的訊息(GossipDigestSynMessage),這種訊息交給其對應的處理器GossipDigestAckVerbHandler處理,具體處理過程在doVerb()方法中,核心程式碼如下:
public void doVerb(MessageIn<GossipDigestSyn> message, int id){
    //...check
    
    List<GossipDigest> gDigestList = gDigestMessage.getGossipDigests();
   
    doSort(gDigestList);

    List<GossipDigest> deltaGossipDigestList = new ArrayList<GossipDigest>();
    Map<InetAddress, EndpointState> deltaEpStateMap = new HashMap<InetAddress, EndpointState>();
    Gossiper.instance.examineGossiper(gDigestList, deltaGossipDigestList, deltaEpStateMap);
    logger.trace("sending {} digests and {} deltas", deltaGossipDigestList.size(), deltaEpStateMap.size());
    MessageOut<GossipDigestAck> gDigestAckMessage = new MessageOut<GossipDigestAck>(MessagingService.Verb.GOSSIP_DIGEST_ACK,
                                                                                    new GossipDigestAck(deltaGossipDigestList, deltaEpStateMap),
                                                                                    GossipDigestAck.serializer);
    Gossiper.instance.checkSeedContact(from);
    MessagingService.instance().sendOneWay(gDigestAckMessage, from);
}
1、對接受到的訊息排序:先按generation排序,如果generation相同,按maxVersion與本地版本差排序; 2、examineGossiper對比接收到的資訊與本節點的差異,本節點需要進一步獲取的訊息由deltaGossipDigestList儲存,本節點需要告訴from節點的資訊由deltaEpStateMap儲存; 3、利用deltaGossipDigestList和deltaEpStateMap封裝成GossipDigestAckMessage訊息,傳送給from節點。

GossipDigestAckMessage

同GossipDigestSynMessage訊息一樣,GOSSIP_DIGEST_ACK型別的訊息由處理器GossipDigestAckVerbHandler處理,也是doVerb()方法,實際上這三個處理器有共同的實現介面IVerbHandler。核心程式碼如下:
 public void doVerb(MessageIn<GossipDigestAck> message, int id){
    List<GossipDigest> gDigestList = gDigestAckMessage.getGossipDigestList();
    Map<InetAddress, EndpointState> epStateMap = gDigestAckMessage.getEndpointStateMap();
   
    if (epStateMap.size() > 0)
    {
        Gossiper.instance.notifyFailureDetector(epStateMap);
        Gossiper.instance.applyStateLocally(epStateMap);
    }

    Map<InetAddress, EndpointState> deltaEpStateMap = new HashMap<InetAddress, EndpointState>();
    for (GossipDigest gDigest : gDigestList)
    {
        InetAddress addr = gDigest.getEndpoint();
        EndpointState localEpStatePtr = Gossiper.instance.getStateForVersionBiggerThan(addr, gDigest.getMaxVersion());
        if (localEpStatePtr != null)
            deltaEpStateMap.put(addr, localEpStatePtr);
    }

    MessageOut<GossipDigestAck2> gDigestAck2Message = new MessageOut<GossipDigestAck2>(MessagingService.Verb.GOSSIP_DIGEST_ACK2,
                                                                                       new GossipDigestAck2(deltaEpStateMap),
                                                                                       GossipDigestAck2.serializer);
    MessagingService.instance().sendOneWay(gDigestAck2Message, from);
}
1、epStateMap 是from節點想要告訴它的訊息,呼叫applyStateLocally方法進行更新; 2、gDigestList是from節點想要進一步更新的訊息,呼叫getStateForVersionBiggerThan方法拿到from節點可以更新的訊息; 3、將2中的訊息封裝成GOSSIP_DIGEST_ACK2訊息傳送給from結點。

GossipDigestAck2Message

由GossipDigestAck2VerbHandler處理器處理,這裡就不貼程式碼,接收到from介面發過來的訊息,進行本地更新即可。 下節學習cassandra的機架感應 參考資料:

相關推薦

Cassandra學習筆記Gossip協議

Gossip協議概述 Cassandra叢集中的節點沒有主次之分,它們通過一種叫做Gossip的協議進行通訊。通過Gossip協議,它們可以知道叢集中有哪些節點,以及這些節點的狀態如何?每一條Gossip訊息上都有一個版本號,節點可以對接收到的訊息進行版本比對,從而得知哪些

三LWIP學習筆記ARP協議

span add 一個 gpo 本質 protoc 更新 通信 網通 一、ARP協議簡介     ARP,全稱 Address Resolution Protocol,譯作地址解析協議,ARP 協議與底層網絡接口密切相關。TCP/IP 標準分層結構中,把 ARP 劃分為了網

Cassandra學習筆記資料讀取

讀取流程 cassandra的資料可能在Memtable中,也可能在多個SSTable中,每個地方都可能有某個column對應的值,怎麼才能讀取最新的值呢?有必要了解下cassandra讀取資料流程: (1)判斷rowcache中是否有需要讀取的資料,如果有直接返回; (2

Cassandra學習筆記機架感應策略

Snitches概述 Cassandra提供了Snitches功能,可以知道叢集中的每個節點所屬資料中心和機架。所有機架感應策略都實現了相同的介面IEndpointSnitch。先來看看Snitches的類圖: IEndpointSnitch介面中提供了比較實用的方法:

Cassandra學習筆記資料模型

Column Column是Cassandra中最小的資料單元,它是一個三元的資料型別,包含name,value,timestamp. Column必須有一個名稱,類似於JAVA中的字串,應用建立後可以動態地設定,Column可以在name上建索引。不要求每個name都有

七LWIP學習筆記傳輸控制協議(TCP)

輸入 post wait syn 快速重傳 擁塞 斷開連接 其他 time 一、協議簡介 1、TCP的必要性 2、TCP的特性 3、連接的定義 4、數據流編號 5、滑動窗口 二、TCP報文 1、報文格式 2、TCP選項 3、緊急數據 4、強迫數據交互 5、報文首部數據結構

六LWIP學習筆記用戶數據報協議(UDP)

端口 數據結構 筆記 udp協議 pos body 校驗 傳輸 連接 一、背景知識 1、傳輸層協議 2、UDP協議 3、端口 4、UDP報文的交付 5、UDP報文格式 6、UDP偽首部與校驗和 二、UDP數據結構 1、報文首部結構 2、控制塊 三、控制塊操作函數 1、使用U

基於libevent的http協議 學習筆記認識基本函式(1)

1. evhttp_new 宣告: struct evhttp *evhttp_new(struct event_base *base); 用途:用於建立一個新的HTTP server, 引數: base(可選)用來接收http事件, (注:可選是什麼意思暫時不清楚,歡迎

Linux鄰居協議 學習筆記 五 通用鄰居項的狀態機機制

       鄰居項的狀態機機制是通用鄰居層最重要的內容,主要是處理鄰居項中狀態的改變,其中包括幾個鄰居狀態的定時器機制,以及鄰居項的更新,solicit請求的傳送等 對於通用鄰居項的狀態機,主要有如下幾個狀態: NUD_INCOMPLETE、NUD_REACHABLE、N

DICOM 協議學習筆記 What is DICOM

digital 互換 生活 內容 文件 hive 網絡 都是 日常生活 什麽是DICOM? Dicom (Digital Imaging and Communications in Medicine)即醫學數字成像和通信,是醫學圖像和相關信息的國際標準(ISO 12052

EZ-USB 68013學習筆記(一)——USB協議描述符

這裡首先感謝電腦圈圈的USB那本書還有稻穀成熟了68013的韌體研究 首先我們需要理解什麼是USB。大家不要把它想複雜了,其實USB就是一種序列通訊方式,它具有自己特有的通訊協議,就是USB通訊協議,有些人可能問,什麼是協議,我覺得協議就好像 兩個人之間的暗號,同樣兩個

Linux鄰居協議 學習筆記 四 通用鄰居項建立、查詢、刪除等相關的函式

上節主要是分析了通用鄰居層鄰居項的垃圾回收機制,這一節主要是分析鄰居項的建立、查詢、刪除等相關的函式,這一節只是介紹函式功能,而沒有涉及狀態機、通用鄰居層的架構等。比如鄰居項刪除函式neigh_destroy,而這個函式主要是通過垃圾回收機制的呼叫才會執行刪除操作;而

學習筆記TCP/IP協議分層與OSI參考模型

1.協議的分層      ISO在制定標準化OSI之前,對網路體系結構相關的問題進行了充分的討論, 最終提出了作為通訊協議設計指標的OSI參考模型。這一模型將通訊協議中必要 的功能分成了7層。通過這些

SAS學習筆記函數應用

不能 oracle 理解 資料 oracl 函數應用 特殊 put acl 今天在做數據需求的時候遇到一些問題,因為不能夠在數據庫裏面做,僅僅好在SAS裏面實現。這就遇到了一些麻煩,須要使用一些函數實現部分功能,如查找字段中某個特殊字符出現的次數,查找某個字符的位置等,

c#學習筆記Application.DoEvents應用

box nbsp net replace 運算 技術 oop blank 假死 Visual Studio裏的摘要:處理當前在消息隊列中的所有 Windows 消息。 交出CPU控制權,讓系統可以處理隊列中的所有Windows消息 比如在大運算量循環內,加Applicati

[C#學習筆記異步編程模式2]BeginInvoke和EndInvoke方法 (轉載)

cti otf 函數返回 編程模式 catch 數值 gin 單線程 blog 為什麽要進行異步回調?眾所周知,普通方法運行,是單線程的,如果中途有大型操作(如:讀取大文件,大批量操作數據庫,網絡傳輸等),都會導致方法阻塞,表現在界面上就是,程序卡或者死掉,界面元素不動了,

.NET學習筆記ADO.NET

技術分享 reader sql語句 bsp 技術 area ada 執行sql 學習 據提供程序: Connection,用來連接數據庫 Command,用來執行SQL語句 DataReader只讀,只進的結果集,一條一條讀取數據 DataAdapter,一個封裝了上面3個

,NET學習筆記ADO.NET

nbsp png alt 學習 log logs ima http blog ,NET學習筆記之ADO.NET

Metasploit學習筆記——情報搜集

user 技術 得到 版本號 域名 listing 避免 ger max 1.情報搜集 1.1外圍信息搜索 1.1.1通過DNS和IP地址挖掘目標網絡信息 (1)whois域名註冊信息查詢(BT5、kali專有):[email protected]

鋒利的JQuery學習筆記JQuery

function 效率 back 一點 ie6 容易 服務器端 pre loading   今天終於看到了最令我興奮的一章:JQuery與Ajax的應用。AJAX即“Asynchronous JavaScript and XML”(異步JavaScript和XML),