本文隶属于专栏《1000个问题搞定大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构和参考文献请见1000个问题搞定大数据技术体系
Flume 的核心是把数据从数据源收集过来,再送到目的地。为了保证输送一定成功,在送到目的地之前,会先缓存数据,待数据真正到达目的地后,删除自己缓存的数据。
Flume分布式系统中最核心的角色是agent,flume采集系统就是由一个个agent所连接起来形成。
一个 Agent 可从客户端或前一个 Agent 接收数据,经过过滤(可选)、路由等操作后,传递给下一个或多个 Agent (完全分布式),直到抵达指定的目标系统。
用户可根据需要拼接任意多个 Agent 构成一个数据流水线。
Flume 将数据流水线中传递的数据称为“Event",每个 Event 由头部和字节数组(数据内容)两部分构成。
其中,头部由一系列 key / value 对构成,可用于数据路由,字节数组封装了实际要传递的数据内容,
通常使用 Avro,Thrift,Protobuf 等对象序列化而成。
关于 Avro 请查看我的博客——Apache Avro是什么?
关于 Thrift 请查看我的博客——Apache Thrift是什么?
关于 Protobuf 请查看我的博客——Protobuf是什么?
Flume 中 Event 可由专门的客户端程序产生,这些客户端程序将要发送的数据封装成 Event 对象, 并调用 Flume 提供的 SDK 发送给 Agent
接下来重点讲解 Agent 内部的组件构成,如图所示。
Agent 内部主要由三个组件构成,分别是 Source, Channel 和 Sink ,其作用和功能如下。
采集组件,用于跟数据源对接,以获取数据
Flume 数据流中接收 Event 的组件,通常从 Client 程序或上一个 Agent 接收数据,并写入一个或多个 Channel 。
为了方便用户使用, Flume 提供了很多 Source 实现,主要包括:
内置 AvroServer ,可接收 Avro 客户端发送的数据,并写入 Channel
内置 ThriftServer ,可接收 Thrift 客户端发送的数据,并写入 Channel
执行指定的 shell ,并从该命令的标准输出中获取数据,写入 Channel 如“ tail -F 文件名”命令,
ExecSource 可实现对数据的实时收集,但考虑到该 Flume Agent 不运行或者指令执行出错时,将无法收集到日志数据,无法保证日志数据的完整性,因而在实际生产环境中很少被采用。
该 Source 可监控指定目录池下文件的变化,一旦发现有新的文件,会将之写入 Channel ,在使用该 Source 时,需要注意两点:
拷贝到监控目录下的文件不可以再修改;目录下不可包含子目录。
使用该 Source 时,通常会指定一个目录作为监控目录,当需要传输数据时,将文件拷贝到该目录下,实现近似实时传输。
由于该 Source 可靠性和稳定性较好,被不少公司采用。
内置 Kafka Consumer ,可从 Kafka Broker 中读取某个 topic 的数据,写入 Channel。
分为 Syslog TCP Source 和 Syslog UDP Source 两种,分别可以接收 TCP 和 UDP 协议发过来的数据,并写入 Channel
可接收 HTTP 协议发来的数据,并写入 Channel 当然,用户也可以根据自己的需要定制 Source 。
如何选择 Flume Source?
在实际生产环境中,存在两种数据源,一种是文件,可采用 ExecSource 或 Spooling Directory Source 收集数据,但考虑到前者无法保证数据完整性,后者实时性较差,通常会自己进行定制,既保证完整性,又具备较高的实时性。
taildirsource 便是一个非常优秀的解决方案,它能实时监控一个目录下文件的变化,实时读取新增数据,并记录断点,保证重启 Agent 后数据不丢失或被重复传输;
另一种是网络数据,这时候可采用 Avro / Thrift source ,并自己编写客户端程序传输数据给该 source 。
传输通道组件,缓存数据,用于从source将数据传递到sink
Channel 是一个缓存区,它暂存 Source 写入的 Event ,直到被 Sink 发送出去。
目前 Fume 主要提供了以下几种 Channel 实现
在内存队列中缓存 Event 。
该 Channel 具有非常高的性能(指 Source 写入和 Sink 读取性能),但一旦断电,内存中数据会丢失,另外,内存不足时,可能导致 Agent ,崩溃。
在磁盘文件中缓存 Event 。
该 Channel 弥补了 MemoryChannel 的不足,但性能会有一定的下降。
支持 JDBC 驱动,进而可将 Event 写入数据库中。
该 Channel 适用于对故障恢复要求非常高的场景。
在 Kafka 中缓存 Event 。
Kafka 提供了高容错性和扩展性,允许可靠地缓存更多数据,这为其他 Sink 重复读取 Channel 中的数据提供了可能(比如发现统计结果有误,重新收集 1 天前的数据进行处理)。
下沉组件,数据发送给最终存储系统或者下一级agent中
sink 负责从 Channel 中读取数据,并发送给下一个 Agent (的 Source )。
Flume 主要提供了以下几种 Sink 实现
这是最常用的一种 Sink ,负责将 Channel 中的数据写入 HDFS ,用户可根据时间或者数据量,决定何时交替形成一个新的文件。
可将 Channel 中的数据写入 HBase ,支持同步和异步两种写人方式。
内置了 Avro / Thrift 客户端,可将 Event 数据通过 Avro / Thrift RPC 发送给指定的 Avro / Thrift Server
将 Channel 中的 Event 数据写入 Solr / ElasticSearch 搜索引擎,在一些场景下,用户需要同时对数据进行离线分析和在线搜索,可同时使用 HDFS Sink 和该 Sink 将数据同时写入 HDFS 和搜索引擎。
将 Channel 中的数据写入 Kafka 中。
Flume 使用事务性的方式保证 Event 传递的可靠性。
Sink 必须在 Event 被存入 Channel 后,或者已经被成功传递给下一个 Agent 后,才能把 Event 从 Channel 中删除掉。
这样数据流里的 Event 无论是在一个 Agent 里还是多个 Agent 之间流转,都能保证可靠。