flume简介

Flume 到底是个啥?一文讲透这个日志采集工具

做数据平台,第一步就是日志采集。要是数据都进不来,后面再牛的架构都是白搭。

Flume 是 Apache 旗下的分布式日志采集工具,主打高可用、高可靠、易扩展。说白了,就是帮你在海量日志场景下,把数据从 A 点搬到 B 点,还不丢数据。

这篇文章我按自己的理解,把 Flume 的核心概念、组件架构捋一遍,尽量讲清楚它到底怎么工作的。本文基于 Flume 1.9.0(可通过官网或包管理工具安装,安装后需在 flume-env.sh 中配置 JAVA_HOME)。

>flume-ng version 
Flume 1.9.0
Source code repository: https://git-wip-us.apache.org/repos/asf/flume.git
Revision: d4fcab4f501d41597bc616921329a4339f73585e
Compiled by fszabo on Mon Dec 17 20:45:25 CET 2018
From source with checksum 35db629a3bda49d23e9b3690c80737f9

先说清楚它到底干啥的

Flume 的核心就一件事:从数据源采数据,传给存储系统。比如你的应用服务器每天产生几十个 GB 的日志,你想把这些日志弄到 HDFS 或 Kafka 里,Flume 就是干这个的。

它的优势,我用自己的话说:

  • 高可用:节点挂了能自动恢复,不至于整个采集链路瘫痪

  • 高可靠:通过持久化机制保证数据不丢,这个后面会细说

  • 分布式:可以横向扩展,日志量大了就加机器

  • 灵活:支持自定义数据源、传输逻辑和存储目标,大部分场景都能覆盖

Flume 的核心架构:一个 Agent 三个组件

Flume 的最小工作单元叫 Agent(代理)。一个 Agent 由三个组件构成:Source(数据源)、Channel(通道)、Sink(接收器)。

多个 Agent 可以串起来,形成一条数据流 pipeline,实现跨节点的数据传输。比如:A 服务器采集 → 发给 B 服务器聚合 → 再发给 C 服务器写入 HDFS。

flume

工作流程就三步:

  1. Source 从数据源(如日志文件、Kafka、网络端口)采集数据,封装为 Event(事件) 发给 Channel;
  2. Channel 是个临时缓冲区,把 Event 先存起来,等 Sink 来取,确保数据不丢失;
  3. Sink 从 Channel 里取 Event,写到目标存储系统(如 HDFS、Kafka)或下一个 Agent 的 Source。

几个必须搞懂的核心概念

事件Event

Event 是 Flume 里数据传输的最小单位,你可以把它理解成一个快递包裹。每个 Event 包含两部分:

  • Header:键值对形式的元信息,比如时间戳、数据来源,用于后续的路由和过滤
  • Body:真正的业务数据,是字节数组格式,比如一条日志的文本内容

举个例子,一条用户行为日志到了 Flume 里,长这样:

Header: {timestamp=1620000000000, source=app-log}  
Body: "user_id=123;action=click;page=home"(字节数组形式)

事件源Source

Source 是数据流入 Flume 的 “入口”,负责从数据源采集数据并转换为 Event 发送到 Channel。Flume 支持丰富的内置 Source,覆盖大多数常见场景:

常用 Source 类型
类型 适用场景 示例配置场景
spooldir 监控目录下的新增文件(如日志文件) 采集应用服务器的本地日志文件
netcat 监听网络端口接收数据 实时接收网络设备推送的日志
kafka 从 Kafka 主题消费数据 对接 Kafka 进行数据中转
exec 执行命令并采集输出(如 tail -F) 实时跟踪日志文件新增内容
http 通过 HTTP 请求接收数据 接收应用程序主动上报的事件
特点与扩展
  • 支持多 Channel 输出:一个 Source 可将 Event 发送到多个 Channel(通过 Channel Selector 控制);
  • 可自定义 Source:若内置类型不满足需求,可通过实现 org.apache.flume.Source 接口开发自定义 Source。

source类型

通道Channel

Channel 是 Flume 可靠性的核心。Source 把数据放进去,Sink 再从里面取,Channel 在中间暂存,确保数据不丢。

常用 Channel 类型

类型 存储方式 可靠性 性能 适用场景
Memory Channel 内存 低(易丢失) 高 非核心数据、对性能要求高的场景
File Channel 本地磁盘 高(持久化) 中 核心数据、需保证不丢失的场景
JDBC Channel 关系型数据库 高 低 需事务支持或跨节点共享数据的场景

Channel Selector(通道选择器)

当一个 Source 对接多个 Channel 时,Selector 决定 Event 发到哪些 Channel。有两种策略:

  • Replicating(默认):复制一份发到所有 Channel,相当于广播
  • Multiplexing:根据 Event Header 里的某个字段值,路由到不同的 Channel

示例配置(Multiplexing):

a1.sources = r1
# 多个channel
a1.channels = c1 c2 c3 c4
a1.sources.r1.selector.type = multiplexing  
# 根据 Header 中的 "state" 属性路由 
a1.sources.r1.selector.header = state
# state=CZ → 发送到 c1 
a1.sources.r1.selector.mapping.CZ = c1
 # state=US → 发送到 c2 和 c3  
a1.sources.r1.selector.mapping.US = c2 c3
# 无匹配时默认发送到 c4  
a1.sources.r1.selector.default = c4

通道类型

接收器Sink

Sink 是数据流出 Flume 的 “出口”,负责从 Channel 读取 Event 并传输到目标存储系统或下一个 Agent。同样,Flume 内置了多种选择:

常用 Sink 类型
类型 目标存储 适用场景
hdfs HDFS 文件系统 海量日志数据持久化存储
kafka 写入 Kafka 主题 对接 Kafka 供下游消费
logger 输出到 Flume 日志(控制台) 调试或临时数据查看
file_roll 写入本地文件 小规模数据本地存储
hbase 写入 HBase 表 需随机读写或实时查询的场景
avro 发送到另一个 Flume Agent 的 Source 跨节点数据传输(多级 Agent 串联)
Sink Group(接收器组)

如果你想提高写入吞吐量,可以把多个 Sink 组成一个组,用轮询或故障转移策略分配任务。比如配三个 hdfs Sink 并行写 HDFS,写入速度翻倍:

  • 支持 round_robin(轮询)或 failover(故障转移)策略;
  • 示例:多个 hdfs Sink 组成 Group,并行写入 HDFS 提升效率。

sink类型

Flume 的灵活性与扩展能力

Flume 的强大不仅在于内置组件,更在于其可扩展性:

  • 拦截器(Interceptor):在 Event 从 Source 到 Channel 之前,你可以加一道”加工工序”。常见的用法是:给每条日志加一个时间戳、过滤掉无效日志、或者从 Body 里提取某个字段放到 Header 里做路由;
  • 序列化器(Serializer):自定义 Event 写入目标系统的格式(如将 Body 转换为 JSON 或 Parquet 格式);
  • 自定义组件:通过接口开发自定义 Source、Channel、Sink,适配特殊业务场景。