从零开始学习数据仓库 | 第三篇:Flume 数据采集基石
今天学习Flume,在构建离线数仓的旅程中,数据采集是第一道关卡。无论是业务服务器上滚动的日志文件,还是散落在各个机器上的系统指标,我们都需要一个可靠的工具把它们搬运到大数据集群(如 HDFS)中。
一、 Flume 概述和优点
Flume 是什么?
简单来说,Flume 就是一个分布式的、高可靠的、高可用的海量日志采集、聚合和传输系统。你可以把它想象成一个不知疲倦的"数据搬运工"。
核心优点:
- 高可靠:基于事务机制,保证数据在传输过程中不丢失(结合 File Channel 可实现断电续传)。
- 高可用:支持多级拓扑结构,以及 Failover(故障转移)和 Load Balance(负载均衡)机制。
- 易扩展:组件化设计,支持自定义 Source、Channel、Sink 和 Interceptor。
- 配置即用 :不需要写一堆 Java 代码,只需编写简单的
.conf配置文件即可启动。
二、 Flume 体系架构
Flume 的运行单元叫做 Agent。一个 Agent 就是一个 JVM 进程,内部由三个核心组件构成,形成一个完美的流水线:
- Source(数据源)
- 负责接收数据。可以是监控日志文件(
Taildir/Exec)、监听网络端口(Netcat/Avro)或读取消息队列(Kafka)。
- 负责接收数据。可以是监控日志文件(
- Channel(通道)
- 数据的缓冲区。Source 读到的数据先放在这里。常用的有
Memory Channel(内存,速度快但断电易丢数据)和File Channel(磁盘,速度稍慢但保证数据安全)。
- 数据的缓冲区。Source 读到的数据先放在这里。常用的有
- Sink(数据接收端)
- 负责把数据从 Channel 取出来,发送到目的地。比如打印到控制台(
Logger)、写入 HDFS(HDFS Sink)或传输给下一个 Agent(Avro Sink)。
- 负责把数据从 Channel 取出来,发送到目的地。比如打印到控制台(
三、 Flume 事务机制:数据不丢的秘诀
Flume 的核心灵魂在于它的事务机制。数据在 Source -> Channel,以及 Channel -> Sink 的传递,都是基于事务的。
- Put 事务:Source 读取数据,打包成事务,放入 Channel。如果成功,提交事务;如果失败,回滚。
- Take 事务:Sink 从 Channel 拉取数据,打包成事务,发送到目的地。如果成功,向 Channel 确认(ACK),删除缓冲区数据;如果失败,回滚。
四、 Flume 启动与官网基础案例
这是官方最基础的 Netcat -> Logger 案例,非常适合用来测试环境。
配置文件(netcat2logger.conf):
conf
# 定义a1的三个组件的名称
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# 定义Source的类型
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444
# 定义Channel的类型
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100
# 定义Sink的类型
a1.sinks.k1.type = logger
# 组装source channel sink
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
启动命令:
(注意:-Dflume.root.logger=INFO,console 必须加上,否则你看不到 Sink 打印的日志)
bash
flume-ng agent -n a1 -c conf -f ${FLUME_HOME}/options/netcat2logger.conf -Dflume.root.logger=INFO,console
启动后,新开一个窗口执行 telnet localhost 44444,随便敲几个字,你就能在 Flume 窗口看到数据打印了。
五、 Flume 高阶实战配置(离线数仓必备)
在实际的离线数仓项目中,单节点、单组件的配置是远远不够的。我们需要应对海量日志、网络抖动和单点故障。
1. 核心利器:Taildir Source + HDFS Sink
这是最经典的日志采集配置。Taildir 支持多目录、正则匹配,并能利用 position file 实现断点续传;HDFS Sink 负责将数据按大小或时间滚动写入。
关键配置片段:
properties
# Taildir Source 断点续传
a1.sources.r1.type = taildir
a1.sources.r1.positionFile = /opt/flume/taildir_position.json
a1.sources.r1.filegroups = f1
a1.sources.r1.filegroups.f1 = /opt/logs/app.*.log
# HDFS Sink 防止小文件
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = hdfs://node01:8020/warehouse/ods/app_log/%Y-%m-%d
a1.sinks.k1.hdfs.rollInterval = 3600 # 1小时切一次
a1.sinks.k1.hdfs.rollSize = 134217728 # 128M切一次 (防止小文件)
a1.sinks.k1.hdfs.rollCount = 0 # 禁用按条数切分
a1.sinks.k1.hdfs.fileType = DataStream # 纯文本存储
2. 多级拓扑(Avro 连接)
如果公司有 100 台服务器,不让它们直接写 HDFS,而是第一层采集节点将数据通过 Avro Sink 发送给汇聚节点,汇聚节点通过 Avro Source 接收后,再统一写入 HDFS。
3. 高可用:故障转移(Failover)与负载均衡(Load Balance)
配置多个 Sink,并组成一个 Sink Group。
- Failover(故障转移):主节点挂了,自动切换备节点。适合对数据顺序有要求的场景。
- Load Balance(负载均衡):数据轮询或随机发送到多个节点,分摊压力。适合无状态的日志收集。
Sink Group 配置示例:
properties
a1.sinkgroups = g1
a1.sinkgroups.g1.sinks = k1 k2
a1.sinkgroups.g1.processor.type = failover # 或 load_balance
a1.sinkgroups.g1.processor.priority.k1 = 10
a1.sinkgroups.g1.processor.priority.k2 = 5
4. 自定义 Interceptor(拦截器)
在数据进入 Channel 之前,我们可以用拦截器对数据进行"清洗"或"打标签"。Flume 自带时间戳拦截器、正则过滤拦截器等。
如果需要复杂逻辑(比如手机号脱敏、JSON 字段解析),可以继承 Interceptor 接口编写自定义 Java 类,打包放入 ${FLUME_HOME}/lib/ 下,然后在配置中指定即可。
💡 学习 Flume 的避坑指南
- 配置格式极其严格 :少一个
s(比如channel写成channels),Flume 启动就会报错,看日志找半天。 - HDFS 权限问题 :写 HDFS 报
Permission denied时,记得在启动命令前加上HADOOP_USER_NAME=hdfs。 - 不要死磕视频案例 :如果是做数仓项目,重点关注
Taildir、HDFS Sink和Interceptor的配置,其他的了解架构即可。
下一篇,我们将进入 dataX的世界。