Apache Flume - File通道

设计
       FileChannel是基于内存队列和WAL设计的。每次事务都是根据事物类型(Take和Put)写到WAL,队列也做相应的修改。每次事务被commited,都会调用fsync确保events被存储在磁盘文件,同时指向该event的指针被放到队列中。这里的队列服务就像其他队列一样:它管理着什么被sink消费。在Take期间,该event的指针从队列被删除。直接从WAL读这个event。由于今天我们有大量可用的RAM,从操作系统的文件缓存中读取也是经常发生的。
       崩溃后,通过重放WALs,队列位置能恢复到崩溃前同样的状态,而那些没有commited的事务被丢弃。重放WALs相当耗时,因此队列本身会周期性的写到磁盘。将队列写到磁盘称为checkpoint。这样,崩溃后,队列首先从磁盘checkpoint文件加载,然后仅仅重放那些队列被最后一次checkpoint到磁盘后commited的事务,这样明显的减少了读取WAL的数量。
       例如,一个channel有2个event,如下所示:
       Apache Flume - File通道
       
       WALs包含3个重要的属性:事务ID、序列号、event数据。每个事务都有唯一的事务Id,并且每个event都有唯一的序列号。事务Id被用来简单的将event分组到同一事务,而序列号在重放log时使用。上图中,事务ID为1,序列号为1,2,3.
       当队列被checkpoint到磁盘,增加序列号,同时序列号也被保存到磁盘。重启时,队列首先从磁盘加载,然后比队列序列号大的任何WAL实体被重放。checkpoin操作期间,队列是locked,以至于没有Put或Take操作可以更改它的状态。如果checkpoint期间允许队列的修改,将导致磁盘存储的队列快照与实际队列不一致。
       在上面例子中,事务1commited后,checkpoint发生,在队列中的结果带着events被保存到磁盘还有序列号4也被保存。
       之后,在事务2中,从队列take一个event:
         Apache Flume - File通道
        
        如果这个时候崩溃了,重启时队列从checkpoint加载,注意,checkpoint发生在事务2前,2个event“a”和“b”都会被加载到队列,之后任何比4大的已经确认的事务被重放,重放后,“a”event从队列被删除。
       上面的设计2点没有考虑到,Take或Put进行中,同时发生checkpoint,会导致数据丢失。假定checkpoint发生在take“a”之后:
         Apache Flume - File通道
        如果此时崩溃,在以上描述的设计下,event“b”被加载进入队列,之后重放比5大的任何WAL实体,事务2被rollback,但是这里的take “a”不会被重放。event “a”被丢失,Put也存在相似的情况。由于这个原因,当队列的checkpoint发生时,仍然在处理中的事务也被写出,以至于可以适当的处理这个问题。
       

实现
       FileChannel在Flume项目的flume-file-channel模块,对应包名为org.apache.flume.channel.file。上面描述的队列对应 FlumeEventQueue类,WAL对应 Log类。队列本身是一个环形数组,通过内存映射文件支撑;而WAL对应一组文件,可以使用 LogFile类和它的子类读写这些文件。
结论
       FileChannel在遇到硬件、软件、环境失败时,给Flume用户提供了持久化的保证,而且具有高的吞吐量。这两个方面对于大多数情况都是比较重要的,因此FileChannel是推荐使用的Channel。

 

你可能感兴趣的:(apache)