一、Flume的事务机制
- Flume的事务机制类似数据库的事务机制:要么都成功,要么都失败
- Flume使用两个独立的事务分别负责从soucrce到channel,以及从channel到sink的事件传递。
1.1 Put 事务流程 - doPut:将批数据先写入临时缓冲区 putList
- doCommit:检查 channel 内存队列是否足够合并
- doRollback:channel 内存队列空间不足,回滚数据
① doCommit检查Channel中是否还有足够的空间来容纳putList中的所有数据,
②如果有doCommit就成功了,putList中的所有数据就会进入到Channel中并清空putList中的数据。
③如果检测的时候发现Channel中的空间不足以容纳putList中的数据的时候,事务就会进行回滚(所谓的回滚就是等一定的时间后,再尝试将putList中的数据发送到Channel)。
注:Flume中有两种source,一种名为Pullable Source,TailDirSource就是这种Source,这种Source是主动拉取数据,而不是由数据源推送过来的,这种Source在回滚等待的过程中source不会继续拉取数据。还有一种是Eventdriven Source,这种Source中的数据是由数据源主动不停的提交数据,在事务回滚的时候,会停止接收数据,这时有可能会产生数据丢失,这种丢失并不是发生在Flume内部,而是发生在Flume和数据源之间。
1.2 Take 事务流程
- doTake:将数据取到临时缓冲区 takeList,并将数据发送到 HDFS
- doCommit:如果数据全部发送成功,则清除临时缓冲区 takeList
- doRollback:数据发送过程中如果出现异常,rollback 将临时缓冲区 takeList 中的数据归还给 channel内存队列
二、Flume的At-least-once提交方式
Flume的事务机制,总的来说,保证了source产生的每个事件都会传送到sink中。但是值得一说的是,实际上Flume作为高容量并行采集系统采用的是At-least-once(传统的企业系统采用的是exactly-once机制)提交方式,这样就造成每个source产生的事件至少到达sink一次,换句话说就是同一事件有可能重复到达。这样虽然看上去是一个缺陷,但是相比为了保证Flume能够可靠地将事件从source,channel传递到sink,这也是一个可以接受的权衡。如上博客中spooldir的使用,Flume会对已经处理完的数据进行标记。
三、Flume的批处理机制
为了提高效率,Flume尽可能的以事务为单位来处理事件,而不是逐一基于事件进行处理。比如上篇博客提到的spooling directory source以100行文本作为一个批次来读取(BatchSize属性来配置,类似数据库的批处理模式)。批处理的设置尤其有利于提高file channle的效率,这样整个事务只需要写入一次本地磁盘,或者调用一次fsync,速度回快很多。