- 《Hadoop权威指南》第14章,简单介绍了Flume
- source —> chanel —> sink,是Flume的基本构建,包含了从数据采集、数据转发、数据存储的一个完整流程
- 与之前使用Flink进行kafka数据的ETL时,一些概念有很多相似之处
- 自己在看完这章之后,觉得Flume还是有很多可以学习的,在这里记录一下
- 因为,自己最开始的安排是,书中讲述的开源组件,只要不是特别重要的,都不会记录 😂
1. Flume概述
Flume的作用
- Flume构建目的:旨在向HDFS批量导入基于事件的海量数据。
- 例如,将一组web服务器中的日志采集以后,批量存储到HDFS中
- Flume具有足够的灵活性,可以将数据导入刀片其他系统,例如HBase或Solr
Flume代理的三种组件
- 一个Flume代理,包含source(数据来源)、channel(连接source和sink的中间组件)、sink(数据目标)三种组件
- source:采集基于事件的数据,将其发送给channel
- channel:对来自source的事件进行存储,然后转发给sink
- sink:将channel转发的数据,进行存储
简单的Flume代理
- source:监听缓冲目录,缓冲目录有新增文件,则将文件内容按行分割为事件,将事件发送给channel
- channel:使用的是file channel,将来自source的事件持久化存储到磁盘;channel将事件发送给sink
- sink:sink将接收到的事件,输出到控制台
Flume代理中的事务
- Flume代理中,存在两个独立的事务,负责
soure ---> channel
和channel ----> sink
的事件传递 - source中,文件被标记为完成(事务提交):事务中所有事件都成功传递给channel
- channel中,事务提交:事务中所有事件都成功记录到sink
- 两种独立的事务,保证了从source收集的事件最终都会到达sink,这种保证是at least once
channel的两种类型
- file channel: 具有持久存储的能力,成功写入channel的事件,在代理重启后,仍然存在
- memory channel: 不具有持久存储的能力,成功写入channel的时间,在代理重启后会丢失。但相对file channel,具有较高的吞吐量
批量处理
- 在此之前,整个代理中数据流都是按事件来介绍的
- 逐个处理事件的效率是非常低下的,因此,Flume是以事务为单位、批量处理事件
- 批量的大小取决于组件类型,且大多数情况下可以配置。
- 示例中,基于缓冲目录的数据转储,每次以100行数据作为一个batch
Flume的配置
- 配置代理的source、channel、sink组件的名称
- 配置source、sink关联的channel
- 配置source的type和type的属性(例如数据来源的目录)、sink的type和type属性(例如数据记录的位置、文件名等)
- 配置channel类型,是file channel还是memory channel
2. HDFS sink
- 基于HDFS的sink,可以设置写入文件目录,文件的前缀、后缀,正在写入文件的前缀(默认后缀是
.tmp
) - HDFS sink时,写入的用户为Flume,如果配置了proxyUser,则写入用户可以指定为真实用户,如lucy
关于文件的分区
- 在写入HDFS文件的过程中,我们通常有这样的需求:例如,希望日志数据按天进行分区
- 按天分区,可以通过文件名实现:文件名中记录了日志所属的day;通过编号,记录同一天的多个日志文件
- 也可以通过目录实现:目录前缀,就代表了日志所属的day
- 这时,有个很重要的前提是,每个事件应该有时间戳,以确定该数据记录到哪个目录或文件
- 通过拦截器,可以为进入source的数据,添加时间戳
3. 扇出(一个source,多个sink)
- 扇出: 一个source向多个channel,即向多个sink传递事件
- 存在两种扇出情况:
(1)source采集的数据,需要记录到不同的sink,例如logger和MySQL
(2)source采集的数据,需要分流:一部分数据写入MySQL,一部分写入HDFS - 针对第一种情况:可以配置多个channel和sink
- 针对第二种情况:可以使用复用选择器实现
多个channel和sink的交付保证:
- 图中,source1 到
channel 1a
是一个事务,source1到channel 1b
是另一个事务 - 如果其中一个事务失败,source1中数据不会被删除,因为需要对失败的事物进行重试
- 实际上,我们将
channel 1b
配置成memory channel,说明是可以容忍事件丢失的 - 如果其对应的事务失败,可以不用要求事务重试的
- 这时,可以将
channel 1b
配置成optional channel
4. 代理分发(事件汇总)
- 真实场景中:一个节点存在一个代理,需要将一组节点的事件写入到同一个sink,而不是多个sink
- 这时,需要对来自多个节点的事件进行汇总,可以通过增加代理层实现
- 如上图所示,多个节点采集到的本地数据通过第一层代理,实现记录;然后记录的数据转发给第二层代理,由第二层代理实现汇总
基于Avro sink-source对连接的两层代理
- Avro sink指定一个ip + port,表示source1中事件,最终会被转发多对应机器的port
- Avro source对机器的port进行监听,如果发现Avro sink将事件送达了port,则从port读取数据作为数据源
- Avro sink和Avro source不是指写入或读取Avro文件,而是利用Avro RPC通信,实现事件的传输
- 自己的总结: Avro sink指定的ip + port,假设为
10.101.3.13:80
, 则Avro source监听的数据来源也是10.101.3.13:80
。通过Avro sink - source对,实现了两层Flume的代理 - 但是,该图只有一个源source,感觉不需要做汇总啊 —— 自己的猜想:图中只展示了一个source,实际应该是逗哥source
交付保证
- 在多层代理下,Flume的事务可以保证事件能可靠地从一个代理传递到下一个代理
- 在示例的Avro sink - source对连接的代理中,channel 1 ----> Avro sink是事务可以提交:
(1)一批事件从Avro sink 传递到Avro source,并且成功批量写入channel 2
(2)Avro source才会向Avro sink返回确认
(3)Avro sink收到确认,channel 1 ----> Avro sink事务才可以提交
5. sink组
- 如果source端的数据只指定一个sink,则出现故障时,整个代理会瘫痪;source端的事件量过大,sink端的压力也会增大
- 通过指定sink组,即多个sink对应一个source,可以实现负载均衡或故障转移
- 注意: 多个sink最终都将事件记录到同一目录,只是文件名不同
自己对扇出和sink组的理解:
- 扇出是同一source硬连接到多个sink,事件肯定会流入指定的sink
- sink组:事件可能流入sink1,也可能流入sink 2,有利于负载均衡和故障转移
6. 常见的Flume组件
- 在本章的最后,给出了不同种类的Flume组件,常见的组件类型
- 例如,sink和source组件:有Avro sink、Avro source
- interceptor: 可以有timestamp和UUID
- 有需要可以查阅该书
7. 总结
Flume概述
- Flume的作用:向HDFS批量导入基于事件的海量数据
- Flume代理的三大基本组件:soure —> channel —> sink
- Flume代理中两个独立的事务,保证了source收集的事件,最终都会到达sink,保证at least once语义
- channel两种类型:file channel 和 memory channel,是否支持久化存储?是否具有较高吞吐等
- Flume的配置
一些典型的Flume配置:
- 基于HDFS sink的配置:通过timestamp拦截器,实现数据分区
- 扇出:一个source硬连接多个sink,分流写入或不分流写入,可设置optional channel
- 分层代理:利用多层代理,实现事件汇总;基于Avro sink - soure对的多层代理;多层代理的交付保证:Avro sink —> Avro source —> channel 2整个流程ok,返回确认 ;才能认为:channel 1 —> Avro sink的事务可以提交
- sink组:一个source 软连接多个sink,有利于负载均衡或故障转移