1、Flume定义
Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。Flume基于流式架构,灵活简单。
说白了就是收集日志的小组件。采集日志的单位是一行一行的。MapReduce不是流式架构的,Spark底层不是流式架构的。Flink、Flume则是流式架构的。流式架构中处理数据的单位是很小的,比如Flume处理数据的单位是一行一行的。而mapReduce则是拿到一个文件才开始处理的。Spark也是一块一块处理的。如果是流式架构,则天生就可以处理数据的。Spark底层可以做Spark streaming,这是在线处理最多的一个模块,尽管底层不是流式架构,但它的转换处理更快,一样可以做在线。流式架构跟在线不是必然联系的,但流式架构做在线处理是有先天优势的。现在Flink上升的很快,因为Flink是纯流式架构的。
Flume在框架中大致的位置如下:
爬虫爬到的数据或者Java后台的数据进来后放到服务器上。还有网络端口数据等,经过Flume采集,然后交给HDFS和Kafka(注意不是直接写到HDFS上的)。它相当于一个全速度管道。
Flume最主要的作用就是,实时读取服务器本地磁盘的数据,将数据写入到HDFS。
为什么数据不直接写到HDFS上?
2、Flume的优点
Flume优点如下:
1.可以和任意存储进程集成。(就是灵活,跟什么都能混搭。注意默认情况下有很多数据源,不行还可以自己写)
2.输入的的数据速率大于写入目的存储的速率,flume会进行缓冲,减小hdfs的压力。(当两边流速不一致的时候,输入可能忽快忽慢,5分钟来了5G,接下来10分钟啥都没有。到了输出速度就可以降下来,起码波动少了很多。相反,如果不使用Flume缓冲,直接传递到HDFS上,效率反而降低了)
3.flume中的事务基于channel,使用了两个事务模型(sender + receiver),确保消息被可靠发送。
Flume使用两个独立的事务分别负责从soucrce到channel,以及从channel到sink的事件传递。一旦事务中所有的数据全部成功提交到channel,那么source才认为该数据读取完成。同理,只有成功被sink写出去的数据,才会从channel中移除。
Sender保证只要能成功提交进来的数据就绝对不会少,百分百进入管道。Receiver向输出提交,只要返回成功,就可以把数据移除管道。
Flume可以保证不丢数据,如此严格的事务管理,可能导致数据重复,而且慢。(事务的两个极端:要么是保证不会重复,但是可能丢数据。要么是保证不会丢数据,但是可能重复。 事务的两个管理的方法,一个是保证消息的不重复,一个是保证消息的可靠性)
3、Flume组成架构
WebServer是数据的来源,HDFS是数据的去向。中间的部分就是Flume的Agent,分为三部分:Source、Channel、Sink(接收器)。Source是跟数据来源对接,Sink是跟数据去向对接,Channel就是蓄水的池子,可以缓存,起到一定的缓冲作用。
数据输入端会把日志一条一条发给Source。Source拿到数据后往Channel推。推的时候经过Put事务流程,它建立一个List(就是Transaction),里面几条数据,然后尝试提交(doCommit)。如果提交成功了,则List会销掉。如果提交失败,则会尝试再提交。如果有个List有5条数据,3条成功了,2条失败了,这个也算失败了,需要再提交一次,以至于可能3条重复了。
数据在出去的时候,也要经过一个事务。需要把数据打包成takeList,再往sink输出。如果其中有一条失败了,takeList会重新写回channel,等待下一次重新takeList。
Source数据输入端的类型有:avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy等。但是目前在企业中使用最广泛的就是日志文件。
- spooling directory。滚动目录。系统会盯着目录看,只要目录中任意文件有变化,就把数据收集上来,然后放到channel中。
- exec:执行一条shell命令。这条shell命令的输出会写到source中。比如 tail -f file命令。只要文件有变化,就写到source中,并输出到channel。
- syslog:追踪系统日志的变化。
- avro:hadoop提供的一种序列化格式。用于Flume两极连接。Flume可以串联,从一个Flume出来,到另一个Flume,在Flume拓扑的时候常会出现这种情况。这样做中间连接的方式就是avro。一个avro出,另一个avro入。
- netcat:网络端口的输出。(nc命令)
Channel是位于Source和Sink之间的缓冲区。
Flume自带两种Channel:Memory Channel(内存通道)和File Channel(文件通道)。内存快,文件安全且大。假如对数据的安全性要求非常高,则使用File;假如对速度的要求更高,则使用Memory。
Memory Channel是基于内存缓存,在不需要关心数据丢失的情景下适用。
File Channel是Flume的持久化Channel。系统宕机不会丢失数据。
Sink组件目的地包括hdfs、kafka、logger、avro、thrift、ipc、file、null、HBase、solr、自定义。但是目前在企业中使用最广泛的是HDFS和Kafka。
- kafka。消息队列。可以把数据做成消息发给Kafka。
- logger:日志。
- avro:同上。
- File:文件。
- 自定义:如果都不满意,可以自己弄。
另外Put和Take事务着重体现的是可靠性而不是不重复。
下面我们来详细介绍一下Flume架构中的组件。
1 Agent
Agent是一个JVM进程,它以事件的形式将数据从源头送至目的。
Agent主要有3个部分组成,Source、Channel、Sink。
2 Source
Source是负责接收数据到Flume Agent的组件。Source组件可以处理各种类型、各种格式的日志数据,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy
3 Channel
Channel是位于Source和Sink之间的缓冲区。因此,Channel允许Source和Sink运作在不同的速率上。Channel是线程安全的,可以同时处理几个Source的写入操作和几个Sink的读取操作。
Flume自带两种Channel:Memory Channel和File Channel。
Memory Channel是内存中的队列。Memory Channel在不需要关心数据丢失的情景下适用。如果需要关心数据丢失,那么Memory Channel就不应该使用,因为程序死亡、机器宕机或者重启都会导致数据丢失。
File Channel将所有事件写到磁盘。因此在程序关闭或机器宕机的情况下不会丢失数据。
4 Sink
Sink不断地轮询Channel中的事件且批量地移除它们,并将这些事件批量写入到存储或索引系统、或者被发送到另一个Flume Agent。
Sink是完全事务性的。在从Channel批量删除数据之前,每个Sink用Channel启动一个事务。批量事件一旦成功写出到存储系统或下一个Flume Agent,Sink就利用Channel提交事务。事务一旦被提交,该Channel从自己的内部缓冲区删除事件。
Sink组件目的地包括hdfs、logger、avro、thrift、ipc、file、null、HBase、solr、自定义。
5 Event
传输单元,Flume数据传输的基本单元,以事件的形式将数据从源头送至目的地。Event由可选的header和载有数据的一个byte array 构成。Header是容纳了key-value字符串对的HashMap。
Flume是流式架构的。就是处理数据的颗粒粒度很细,这里是以event为粒度来处理数据的。比如来了一个日志源头,tail file或spooling dir,这两个东西就是以行为单位监视的。一行数据会作为二进制数据放到Byte Payload中。
Header存放的数据的属性,一般的源头Header是空的,除非是一些特殊的东西,比如自定义的源,需要存放一些属性进Header。
4、Flume拓扑结构
Flume的拓扑结构如图所示:
串联:
这种模式是将多个flume给顺序连接起来了(串联),从最初的source开始到最终sink传送的目的存储系统。这个实际上就是多级缓冲(好处)。此模式不建议桥接过多的flume数量, flume数量过多不仅会影响传输速率,而且一旦传输过程中某个节点flume宕机,会影响整个传输系统(坏处)。
复制和多路复用:
Flume支持将事件流向一个或者多个目的地(一个进入HDFS、一个进入JMS、一个进入多级缓冲)。这种模式将数据源复制到多个channel中,每个channel都有相同的数据,sink可以选择传送的不同的目的地。
负载均衡与故障转移:
Flume支持使用将多个sink逻辑上分到一个sink组,flume将数据发送到不同的sink,主要解决负载均衡和故障转移问题。注意发往三个地方的数据是不一样的。
这种模式是我们最常见的,也非常实用,日常web应用通常分布在上百个服务器,大者甚至上千个、上万个服务器。产生的日志,处理起来也非常麻烦。用flume的这种组合方式能很好的解决这一问题,每台服务器部署一个flume采集日志,传送到一个集中收集日志的flume,再由此flume上传到hdfs、hive、hbase、jms等,进行日志分析。
其实Flume这个东西是很占资源的,它是用Java写的,性能不高。
5、Flume Agent内部原理
Source进入Channel前,需要先进入Channel处理器。处理器会先把消息发给拦截器(inceptor),对消息进行预处理。消息拿来之后,不符合需要,可以简单做一个形式的转变,掐头去尾之类的。但是拦截器不能写太复杂的逻辑,否则性能影响太高,非常复杂的ETL显示就不合适。
数据发回来Channel处理器后会交给Channel选择器。顾名思义,就是选择这条消息应该去哪个Channel。注意,根据前面的拓扑图,一个Source可能对应多个不同的Channel。Channel选择器可以有:
1 群发。
2 Multiplexing。来一条消息时选择:这条消息只会去往一个Channel。这个好处是针对数据来源把数据分为若干份。不同的Channel接不同的Sink,不同的Sink去往不同的数据沉淀。相当于对数据进行分流。
Channel拿到数据后,经过Sink处理器,决定哪个Sink会从哪个Channel拿数据。一个Channel可以对应一个或多个Sink。比如Channel_1可以对应3个Sink,一条消息要么去1、要么去2、要么去3,但不是3个都去。可以轮询(轮流来)或负载均衡(看哪个比较闲)。
Flume的重点是要记住事务的处理方式。