先給出答案:網絡
須要結合具體使用的source、channel和sink來分析,具體結果可看本文最後一節。code
一提到事務,咱們首先就想到的是MySQL中的事務,事務就是將一批操做作成原子性的,即這一批要麼都成功,要麼都失敗。對象
一樣的道理,在flume中也有事務,那麼Flume中的事務在哪一個地方呢?在Flume中的批量操做又是指什麼呢?blog
在Flume中一共有兩個事務,一個是在Source到Channel之間,一個是Channel到Sink之間。在Source到Channel之間的叫put事務,在Channel到Sink之間的叫Take事務。事務
從source到channel過程當中,數據在flume中會被封裝成Event對象,也就是一批event,把這批event放到一個事務中,把這個事務也就是這批event一次性的放入channel中。同理,Take事務的時候,也是把這一批event組成的事務統一拿出來到sink放到HDFS上。ip
接下來咱們看下這兩個事務具體是怎麼實現的:ci
事務確定有的兩個特性就是:成功了提交,失敗了回滾。it
咱們先考慮Put事務的正常的狀況,即任務成功狀況。io
如圖所示:event
事務開始的時候會調用一個doPut
方法,doPut
方法將一批數據(多個event)batch data 放在putList中,而這批數據「批」的大小取決於配置的 batch size
的參數的值。而putList的大小取決於配置channel的參數transaction capacity
的大小,這個參數的大小就體如今putList上了。(tips:channel的另外一個參數capacity
指的是channel的容量)。
如今這批數據順利的放到putList以後,接下來能夠調用doCommit
方法,把putList中全部的event放到channel中,成功放完以後就清空putList。
以上是順利的狀況下,那若是事務進行的過程當中出問題了怎麼解決呢?
第一種問題:數據傳輸到channel過程出問題
在doCommit提交以後,事務在向channel放的過程當中,事務容易出問題。好比:sink那邊取數據慢,而source這邊放數據速度快,就容易形成channel中的數據的積壓,這個時候就會形成putList中的數據放不進去。那如今事務出問題了,如何解決呢?
經過調用doRollback方法,doRollback方法會進行兩項操做:一、將putList清空; 二、拋出channelException異常。這個時候source就會捕捉到doRollback拋出的異常,而後source就會把剛纔的一批數據從新採集一下,採集完以後從新走事務的流程。這就是事務的回滾。
(putList的數據在向channel發送以前先檢查一下channel的容量可否放得下,若是放不下,就一個都不放。)
第二種問題:數據採集過程出問題
有這麼種場景,source採集數據時候採用的是tailDir source,而咱們由於某種緣由將監控的目錄文件刪除,這個時候就會出現問題,一樣地,出現問題的解決方式是調用doRollback方法來對事務進行回滾。
Take事務和Put事務很類似。
一樣地,咱們先不考慮doRollback,先考慮順利不出問題的狀況下事務的完成。
如圖所示:
Take事務一樣也有takeList,HDFS sink配置也有一個 batch size,這個參數決定sink從channel取數據的時候一次取多少個,因此這batch size 得小於takeList的大小,而takeList的大小取決於transaction capacity
的大小,一樣是channel 中的參數。
Take事務流程:事務開始後,doTake方法會將channel中的event剪切到takeList中,固然,後面接的是HDFS Sink的話,在把channel中的event剪切到takeList中的同時也往寫入HDFS的IO緩衝流中放一份event(數據寫入HDFS是先寫入IO緩衝流而後flush到HDFS)。
當takeList中存放了batch size 數量的event以後,就會調用doCommit方法,doCommit方法會作兩個操做:一、針對HDFS Sink,手動調用IO流的flush方法,將IO流緩衝區的數據寫入到HDFS磁盤中;二、而後直接清空takeList中的數據。
以上是順利的狀況下,那若是事務進行的過程當中出問題了怎麼解決呢?
何時最容易出問題呢?——flush到HDFS的時候組容易出問題
如:flush到HDFS的時候,可能因爲網絡緣由超時致使數據傳輸失敗,這個時候一樣地調用doRollback方法來進行回滾,回滾的時候,因爲takeList中還有備份數據,因此將takeList中的數據原封不動地還給channel,這時候就完成了事務的回滾。
可是,若是flush到HDFS的時候,數據flush了一半以後出問題了,這意味着已經有一半的數據已經發送到HDFS上面了,如今出了問題,一樣須要調用doRollback方法來進行回滾,回滾並無「一半」之說,它只會把整個takeList中的數據返回給channel,而後繼續進行數據的讀寫。這樣開啓下一個事務的時候就容易形成數據重複的問題。
因此,在某種程度上,flume對數據進行採集傳輸的時候,它有可能會形成數據的重複,可是其數據不丟失。
這個問題須要分狀況來看,須要結合具體使用的source、channel和sink來分析。
首先,分析source:
(1)exec source ,後面接 tail -f
,這個數據也是有可能丟的。
(2)TailDir source ,這個是不會丟數據的,它能夠保證數據不丟失。
其次,分析sink:
(1)hdfs sink,數據有可能重複,可是不會丟失。
通常生產過程當中,都是使用 **TailDir source **和 HDFS sink,因此數據會重複可是不會丟失。
最後,分析channel 要想數據不丟失的話,仍是要用 File channel,而memory channel 在flume掛掉的時候仍是有可能形成數據的丟失的。