storm的acker機制

1、簡介:

storm中有一個很重要的特性:
保證發出的每一個tuple都會被完整處理。一個tuple被徹底處理的意思是: 這個tuple以及由這個tuple所產生的全部的子tuple都被成功處理。若是任一個消息在timeout所指定的時間內沒有完成處理,那這個tuple就失敗了。算法

2、原理:

acker並不會爲每一個tuple都分配內存空間來完成跟蹤,而是利用了一個很是巧妙的算法,這個算法只需使用恆定的20字節就能夠完成整個tuple樹的跟蹤數據結構

具體原理:

acker對於每一個spout-tuple保存一個ack-val的校驗值,它的初始值是0, 而後每發射一個tuple/ack一個tuple,那麼tuple的id都要跟這個校驗值異或一下,
而且把獲得的值更新爲ack-val的新值。那麼假設每一個發射出去的tuple都被ack了, 那麼最後ack-val必定是0(由於一個數字跟本身異或獲得的值是0)。 spa

通俗理解:

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

消息內容:{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後會將該tuple和MessageId發送到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。it

4. 當全部子tuple都被ack以後,val會被異或成0,OK 整個tuple樹執行跟蹤完成。 原理

場景分析:

1. 因爲對應的task掛掉了,一個tuple沒有被ack: storm的超時機制在超時以後會把這個tuple標記爲失敗,從而能夠從新處理。 map

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

3. Spout掛掉了: 在這種狀況下給spout發送消息的消息源負責從新發送這些消息。好比Kestrel和RabbitMQ在一個客戶端斷開以後會把全部」處理中「的消息放回隊列。 因而可知storm的高度容錯性。

相關文章
相關標籤/搜索