理解storm的ACKER機制原理


一、簡介:
   
  storm中有
個很重要的特性:    

           保證發出的每個tuple都會被完整處理。一個tuple被完全處理的意思是: 這個tuple以及由這個tuple所產生的所有的子tuple都被成功處理。
          如果任一個消息在timeout所指定的時間內沒有完成處理,那這個tuple就失敗了。



二、原理:
    

        acker並不會為每個tuple都分配內存空間來完成跟蹤,而是利用了一個非常巧妙的算法,這個算法只需使用恆定的20字節就可以完成整個tuple樹的跟蹤。
     
   具體原理:

         acker對於每個spout-tuple保存一個ack-val的校驗值,它的初始值是0, 然后每發射一個tuple/ack一個tuple,那么tuple的id都要跟這個校驗值異或一下,
        並且把得到的值更新為ack-val的新值。那么假設每個發射出去的tuple都被ack了, 那么最后ack-val一定是0(因為一個數字跟自己異或得到的值是0)。

  通俗理解:
         

       1.在spout產生一條tuple時,會向acker發送一條信息,讓ack來進行跟蹤,消息內容:
             

{spout-tuple-id { :spout-task task-id :val ack-val}}
              spout-tuple-id:這條tuple的id,每條tuple都會產生一個隨機的MessageId
              task-id:產生這條tuple的id,spout可能有多個task,每個task都會被分配一個唯一的taskId
              ack-val:默認值為0,用來跟蹤tuple

      
                  
     2.acker會在自己的map(類型為TimeCacheMap)里保存這條記錄。 這就是acker對spout-tuple進行跟蹤的核心數據結構, 對於每個spout-tuple所產生的tuple樹的跟蹤
       都只需要保存上面這條記錄。acker后面會檢查:val什么時候變成0,變成0, 說明這個spout-tuple產生的tuple都處理完成了。
     
    3.spout在發送完消息給acker后會將該tupleMessageId發送到boltTask。boltTask在創建子tuple時並不會向acker發送消息讓其跟蹤,而是很巧妙的省略了這一步:
      bolt在發射一個新的bolt的時候會把這個新tuple跟它的父tuple的關系保存起來(strom稱之為anchoring)。然后在ack tuple的時候,storm會把要ack的tuple的id, 以及
     這個tuple新創建的所有的tuple的id的異或值發送給acker。消息格式是:(spout-tuple-id,tmp-ack-val)執行完這一步后,ack-val的值就變成了所有子tuple的id的異或值
      ps:storm使用一致性哈希來把一個spout-tuple-id對應到acker, 因為每一個tuple知道它所有的祖宗的tuple-id, 所以它自然可以算出要通知哪個acker來ack

    4.當所有子tuple都被ack之后,val會被異或成0,OK 整個tuple樹執行跟蹤完成。


場景分析:

     1. 由於對應的task掛掉了,一個tuple沒有被ack: storm的超時機制在超時之后會把這個tuple標記為失敗,從而可以重新處理。

     2. Acker掛掉了: 這種情況下由這個acker所跟蹤的所有spout tuple都會超時,也就會被重新處理。

     3. Spout掛掉了: 在這種情況下給spout發送消息的消息源負責重新發送這些消息。比如Kestrel和RabbitMQ在一個客戶端斷開之后會把所有”處理中“的消息放回隊列。

    由此可見storm的高度容錯性。

 

    原文鏈接:http://blog.itpub.net/29754888/viewspace-1261363/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM