(课堂笔记)Flume(日志采集传输,流式架构)基础使用(对比 Kafka 理解:ZooKeeper = 分布式系统的“管家“ + “通知中心“)

本文详细介绍了Hadoop启动后的操作流程,包括HDFS基本操作、MapReduce示例运行、Flume日志采集配置以及ZooKeeper的核心概念。


主要内容包括:

  1. Hadoop环境验证和HDFS操作
  • 通过jps命令验证Hadoop进程
  • 创建用户目录和上传测试文件到HDFS
  • 运行MapReduce示例程序
  1. Flume日志采集配置
  • 配置netcat到控制台的简单示例
  • 设置文件到HDFS的采集流程
  • 模拟网站日志采集的完整方案
  1. ZooKeeper核心概念
  • 解释ZooKeeper在分布式系统中的作用
  • 对比Kafka和HBase中ZooKeeper的不同应用
  • 提供实际操作命令和练习
  1. 数据处理流程
  • 从日志生成到Flume采集
  • HDFS存储到Hive分析的全流程
  • 包含完整的SQL查询示例

文章通过清晰的步骤说明和实际操作命令,帮助读者掌握大数据生态系统中关键组件的使用方法和相互关系。


梳理补充优化老师的课堂笔记,现在看笔记,我完全不会操作了。Hadoop已经启动了,接下来是怎么做的?

这里按回车太快,忘记贴笔记原文了,AI竟然也能回答的有模有样,真是智能!


不会操作,一是老师讲太快,没有完全记住。二是今天的笔记有缺失,没有之前的详细。最重要的是,教室的电脑死机了重启耗费太多时间,等我想跟着老师做的时候,完全不知道从哪下手了。还好AI足够给力,把我缺的操作补起来了。


看起来你的笔记可能跳过了关键的操作步骤。我先帮你把Hadoop启动后的标准操作流程梳理出来,并补充常见的"卡住"点和检查方法。


第一步:确认Hadoop是否真的启动了

在继续之前,先快速确认一下:

bash

复制代码
jps

你应该能看到以下至少4个进程(如果是单机伪分布式):

text

复制代码
NameNode
DataNode
SecondaryNameNode
ResourceManager
NodeManager

如果缺少NameNodeResourceManager,说明没启动成功,需要先解决。

第二步:HDFS的基本操作(必须先做的事)

Hadoop启动后,HDFS是空的,你需要:

1️⃣ 创建用户目录

bash

复制代码
hdfs dfs -mkdir -p /user/你的用户名

2️⃣ 上传数据到HDFS

bash

复制代码
# 本地创建一个测试文件
echo "hello hadoop" > test.txt

# 上传到HDFS
hdfs dfs -put test.txt /user/你的用户名/

3️⃣ 验证文件是否成功

bash

复制代码
hdfs dfs -ls /user/你的用户名/
hdfs dfs -cat /user/你的用户名/test.txt

第三步:运行一个MapReduce示例(验证Hadoop能用)

Hadoop自带示例jar包,用来测试:

bash

复制代码
# 找到示例jar的位置(通常在Hadoop安装目录下)
find /home -name "hadoop-mapreduce-examples-*.jar" 2>/dev/null
# 或者
ls $HADOOP_HOME/share/hadoop/mapreduce/

# 运行wordcount示例
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar wordcount \
  /user/你的用户名/test.txt \
  /user/你的用户名/output

查看结果:

bash

复制代码
hdfs dfs -cat /user/你的用户名/output/part-r-00000

第四步:接下来你真正想做什么?(选择一条路)

你的目标 下一步操作
学习MapReduce编程 写一个WordCount Java程序 → 打包成jar → 用hadoop jar提交
学习Hive 启动Hive元数据服务和Hive CLI
学习HBase 启动HBase(start-hbase.sh),创建表,插入数据
学习Spark 提交Spark任务(需要Scala/Python代码)
我只是想用Hadoop存文件 hdfs dfs -put/get 就够了

❗常见问题排查(针对"不会操作了")

问题1:jps看不到NameNode

bash

复制代码
# 重新格式化并启动
hdfs namenode -format
start-dfs.sh

问题2:上传文件报错"No such file or directory"

→ 目录不存在,先mkdir -p创建父目录

问题3:没有$HADOOP_HOME环境变量

bash

复制代码
export HADOOP_HOME=/你的hadoop安装路径
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

问题4:Web界面打不开

  • NameNode管理界面:http://你的虚拟机IP:9870

  • 检查防火墙:systemctl stop firewalld


建议你立刻做的事

  1. 先执行jps,把输出发给我

  2. 告诉我你是学习用途 还是做项目 ?笔记里接下来提到的是MapReduce / Hive / HBase / Spark中的哪一个?

我会根据你的实际进度,帮你把缺失的操作步骤完整补回笔记


这里发了笔记原文

Flume : 是一个日志采集,传输的系统。基于流式架构。

并且高可用,高可靠,分布式。

......


太好了!你的Flume笔记内容很全,但缺少启动Hadoop后的具体操作顺序 ,而且笔记里写"默认启动zookeeper"容易让人困惑。我帮你重新梳理+补充缺失步骤 ,让你知道现在到底该做什么


📌 你的现状(Hadoop已启动) → 接下来操作顺序

✅ 第一步:确认环境(5分钟)

bash

复制代码
# 1. 确认Hadoop正常
jps  # 应该看到NameNode, DataNode, ResourceManager, NodeManager

# 2. 确认HDFS可用(Flume要写数据到HDFS)
hdfs dfs -ls /  # 能正常列出目录即可

# 3. 创建Flume在HDFS上的根目录(重要!)
hdfs dfs -mkdir -p /flume

⚠️ 你的笔记里写的node100:9000,需要改成你的实际Hadoop地址:

bash

复制代码
# 检查你的core-site.xml配置
cat $HADOOP_HOME/etc/hadoop/core-site.xml | grep fs.defaultFS
# 假设输出是 hdfs://localhost:9000 或 hdfs://你的IP:9000

📝 第二步:先跑通最简单的示例(netcat → console)

这是验证Flume本身是否能工作的必做测试

1️⃣ 创建配置文件

bash

复制代码
mkdir -p /opt/module/flume/job
vim /opt/module/flume/job/flume-netcat-logger.conf

把你的笔记中的配置完整粘贴进去(你的笔记这段是正确的)

2️⃣ 启动Flume Agent

bash

复制代码
cd /opt/module/flume
bin/flume-ng agent \
  -c conf/ \
  -n a1 \
  -f job/flume-netcat-logger.conf \
  -Dflume.root.logger=INFO,console

3️⃣ 发送测试数据(新开一个终端窗口)

bash

复制代码
nc localhost 8888
# 然后输入 hello flume 回车
# 再输入 test message 回车

4️⃣ 观察效果

Flume启动的窗口应该会打印出:

text

复制代码
Event: { headers:{} body: 68 65 6c 6c 6f 20 66 6c 75 6d 65 hello flume }

成功标准:能看到Event输出 → Flume正常


📁 第三步:跑通"文件 → HDFS"示例(你笔记里的第二个)

1️⃣ 准备测试文件

bash

复制代码
mkdir -p /opt/module/flume/test
touch /opt/module/flume/test/tail.txt

2️⃣ 修改配置文件中的HDFS路径

你的配置里写的是hdfs://node100:9000,需要改成你的实际地址:

bash

复制代码
vim /opt/module/flume/job/flume-file-hdfs.conf

把这一行:

text

复制代码
a2.sinks.k2.hdfs.path = hdfs://node100:9000/flume/%Y%m%d/%H

改成(查看你的Hadoop地址):

bash

复制代码
# 先查看你的HDFS地址
hdfs getconf -confKey fs.defaultFS
# 假设输出是 hdfs://localhost:9000,就改成:
a2.sinks.k2.hdfs.path = hdfs://localhost:9000/flume/%Y%m%d/%H

3️⃣ 启动Flume(新终端窗口1)

bash

复制代码
cd /opt/module/flume
bin/flume-ng agent -c conf/ -n a2 -f job/flume-file-hdfs.conf -Dflume.root.logger=INFO,console

4️⃣ 模拟产生日志(新终端窗口2)

bash

复制代码
# 往监控文件里追加数据
echo "2025-01-01 10:13:34 INFO User login success" >> /opt/module/flume/test/tail.txt
echo "2025-01-01 10:15:22 WARN User logout" >> /opt/module/flume/test/tail.txt
echo "2025-01-01 10:20:45 ERROR Database timeout" >> /opt/module/flume/test/tail.txt

5️⃣ 检查HDFS结果

bash

复制代码
# 查看HDFS上的文件(注意日期目录会自动生成)
hdfs dfs -ls /flume/
hdfs dfs -ls /flume/$(date +%Y%m%d)/$(date +%H)/
hdfs dfs -cat /flume/$(date +%Y%m%d)/$(date +%H)/logs-*

成功标准:能看到你刚echo的内容出现在HDFS文件中


🎯 第四步:你的实际需求(网站日志采集)

你笔记最后提到的网站日志场景,完整流程应该是:

完整采集链路

bash

复制代码
# 1. 创建Flume配置文件(使用taildir source,比exec更可靠)
# 2. 启动Flume采集
# 3. 网站产生日志 → Flume实时采集 → 写入HDFS
# 4. 在Hive中建表查询

我可以帮你写一个生产级别的配置,解决你笔记里的埋点采集需求,需要吗?


⚠️ 你笔记中需要修正的地方

笔记原话 问题 正确做法
"默认启动zookeeper" Flume不需要ZK Flume独立运行,只有HBase/Kafka需要ZK
hdfs://node100:9000 硬编码主机名 改成你的实际HDFS地址
使用exec source 容易丢数据 生产环境用taildir source

🚀 你现在立刻做的事

选择一条路,告诉我:

  1. "我想先跑通netcat示例" → 按第二步操作,把报错发我

  2. "我想直接跑通文件到HDFS" → 按第三步操作,告诉我hdfs getconf的输出

  3. "我要做网站日志采集到Hive分析" → 我直接给你生产级配置+完整SQL

jps的输出和hdfs getconf -confKey fs.defaultFS的结果发我,我帮你把命令里的地址全部替换正确。


用的教室环境,统一安装的虚拟机,环境应该和老师的一样。

bash 复制代码
[hadoop@node100 hadoop-3.3.0]$ jps
2275 DataNode
3139 Jps
2084 NameNode
2732 ResourceManager
3004 NodeManager
2447 SecondaryNameNode
[hadoop@node100 hadoop-3.3.0]$ hdfs getconf -confKey fs.defaultFS
hdfs://node100:9000
[hadoop@node100 hadoop-3.3.0]$

完美!你的环境配置正确,node100:9000就是老师配置的HDFS地址。


现在直接按照下面的步骤操作即可。


🎯 你现在立刻按顺序执行(从0开始)

第一步:确认Flume安装位置

bash

复制代码
# 找到Flume安装目录
ls /opt/module/ | grep flume
# 或者
find /home -name "flume" -type d 2>/dev/null

如果没有Flume,需要先安装。如果有,记录下路径(假设是/opt/module/flume


第二步:创建Flume作业目录和测试文件

bash

复制代码
# 创建job目录
mkdir -p /opt/module/flume/job

# 创建测试文件目录(用于第二个示例)
mkdir -p /opt/module/flume/test

# 创建测试文件
touch /opt/module/flume/test/tail.txt

第三步:跑通第一个示例(netcat → 控制台)

3.1 创建配置文件

bash

复制代码
vim /opt/module/flume/job/flume-netcat-logger.conf

i 进入编辑模式,完整粘贴以下内容:

properties

复制代码
# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 8888

# Describe the sink
a1.sinks.k1.type = logger

# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

ESC,输入 :wq 保存退出。

3.2 启动Flume(在当前终端

bash

复制代码
cd /opt/module/flume
bin/flume-ng agent -c conf/ -n a1 -f job/flume-netcat-logger.conf -Dflume.root.logger=INFO,console

你会看到Flume启动日志,最后停在那里不动(等待数据)。

3.3 发送测试数据(新开一个终端窗口

bash

复制代码
# SSH连接到node100(如果已经在新终端就跳过)
ssh hadoop@node100

# 发送数据
nc localhost 8888

然后输入:

text

复制代码
hello flume

按回车

再输入:

text

复制代码
test message

按回车

3.4 观察效果

回到第一个终端窗口,你应该看到类似这样的输出:

text

复制代码
Event: { headers:{} body: 68 65 6c 6c 6f 20 66 6c 75 6d 65 hello flume }
Event: { headers:{} body: 74 65 73 74 20 6d 65 73 73 61 67 65 test message }

成功!Ctrl+C 停止这个Flume任务,继续下一步。


第四步:跑通第二个示例(文件 → HDFS)

4.1 创建配置文件

bash

复制代码
vim /opt/module/flume/job/flume-file-hdfs.conf

粘贴以下内容(已经改好node100:9000):

properties

复制代码
# Name the components on this agent
a2.sources = r2
a2.sinks = k2
a2.channels = c2

# Describe/configure the source
a2.sources.r2.type = exec
a2.sources.r2.command = tail -F /opt/module/flume/test/tail.txt

# Describe the sink
a2.sinks.k2.type = hdfs
a2.sinks.k2.hdfs.path = hdfs://node100:9000/flume/%Y%m%d/%H
#上传文件的前缀
a2.sinks.k2.hdfs.filePrefix = logs-
#是否按照时间滚动文件夹
a2.sinks.k2.hdfs.round = true
#多少时间单位创建一个新的文件夹
a2.sinks.k2.hdfs.roundValue = 1
#重新定义时间单位
a2.sinks.k2.hdfs.roundUnit = hour
#是否使用本地时间戳
a2.sinks.k2.hdfs.useLocalTimeStamp = true
#积攒多少个Event才flush到HDFS一次
a2.sinks.k2.hdfs.batchSize = 100
#设置文件类型,可支持压缩
a2.sinks.k2.hdfs.fileType = DataStream
#多久生成一个新的文件
a2.sinks.k2.hdfs.rollInterval = 60
#设置每个文件的滚动大小
a2.sinks.k2.hdfs.rollSize = 134217700
#文件的滚动与Event数量无关
a2.sinks.k2.hdfs.rollCount = 0

# Use a channel which buffers events in memory
a2.channels.c2.type = memory
a2.channels.c2.capacity = 1000
a2.channels.c2.transactionCapacity = 100

# Bind the source and sink to the channel
a2.sources.r2.channels = c2
a2.sinks.k2.channel = c2
4.2 先在HDFS创建目录(重要!)

bash

复制代码
hdfs dfs -mkdir -p /flume
4.3 启动Flume(当前终端)

bash

复制代码
cd /opt/module/flume
bin/flume-ng agent -c conf/ -n a2 -f job/flume-file-hdfs.conf -Dflume.root.logger=INFO,console
4.4 生成测试数据(新开终端

bash

复制代码
# 模拟网站日志
echo "2025-05-28 10:13:34 INFO User login success" >> /opt/module/flume/test/tail.txt
echo "2025-05-28 10:15:22 WARN User logout" >> /opt/module/flume/test/tail.txt
echo "2025-05-28 10:20:45 ERROR Database timeout" >> /opt/module/flume/test/tail.txt
4.5 查看HDFS结果(新终端)

bash

复制代码
# 等10-20秒让Flume处理
hdfs dfs -ls /flume/
# 查看具体文件(日期目录会自动生成)
hdfs dfs -ls /flume/20250528/10/
# 查看文件内容
hdfs dfs -cat /flume/20250528/10/logs-*

你应该能看到刚写入的三条日志。

成功! Flume已经将文件数据实时采集到HDFS了。


🎯 现在你要做的网站日志采集(实战场景)

既然环境已经验证通过,现在可以对接你的网站日志了。

创建生产级配置文件(用taildir,比exec更好)

bash

复制代码
vim /opt/module/flume/job/flume-weblog-hdfs.conf

properties

复制代码
# 生产环境推荐配置
a3.sources = r3
a3.sinks = k3
a3.channels = c3

# 使用taildir source(支持断点续传)
a3.sources.r3.type = taildir
a3.sources.r3.positionFile = /opt/module/flume/taildir_position.json
a3.sources.r3.filegroups = f1
a3.sources.r3.filegroups.f1 = /var/log/your-app/pinduoduo_server.log
a3.sources.r3.filegroups.f1.header.logtype = web

# 写入HDFS
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://node100:9000/user/hive/warehouse/weblog_database.db/user_behavior_log/dt=%Y%m%d/
a3.sinks.k3.hdfs.filePrefix = log-
a3.sinks.k3.hdfs.round = true
a3.sinks.k3.hdfs.roundValue = 1
a3.sinks.k3.hdfs.roundUnit = hour
a3.sinks.k3.hdfs.useLocalTimeStamp = true
a3.sinks.k3.hdfs.batchSize = 100
a3.sinks.k3.hdfs.fileType = DataStream
a3.sinks.k3.hdfs.rollInterval = 3600
a3.sinks.k3.hdfs.rollSize = 134217728
a3.sinks.k3.hdfs.rollCount = 0

a3.channels.c3.type = memory
a3.channels.c3.capacity = 10000
a3.channels.c3.transactionCapacity = 1000

a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3

然后在Hive中建表分析

sql

复制代码
-- 创建外部表
CREATE EXTERNAL TABLE user_behavior_log (
    log_time STRING,
    log_level STRING,
    user_ip STRING,
    message STRING
)
PARTITIONED BY (dt STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
LOCATION '/user/hive/warehouse/weblog_database.db/user_behavior_log';

-- 修复分区(自动加载HDFS上的数据)
MSCK REPAIR TABLE user_behavior_log;

-- 查询分析
SELECT 
    dt AS 日期,
    COUNT(1) AS 用户行为数,
    COUNT(DISTINCT user_ip) AS 独立IP数
FROM user_behavior_log
WHERE log_level = 'INFO'
GROUP BY dt;

📌 你现在告诉我

  1. 第一个示例跑通了吗?(看到Event输出)

  2. 第二个示例跑通了吗?(HDFS上有文件)

  3. 你的网站日志文件实际路径是什么?(我帮你改配置中的路径)

  4. 需要我帮你写完整的Hive SQL分析语句吗?

把执行结果或报错直接贴过来,我帮你解决。


第一个示例、第二个示例都跑通了。网站日志采集(实战场景)没看懂,网站日志文件实际路径没有,现在是教学环境,没有自己的网站。


太好了!你已经跑通了两个示例,说明Flume环境完全正常。既然现在是教学环境 ,没有真实网站日志,那我们就模拟网站日志来学习整个流程。


🎯 教学环境下的完整实战(模拟网站日志采集)

你将学会:模拟产生日志 → Flume采集 → 存入HDFS → Hive分析


第一步:模拟网站日志产生(写个脚本)

1.1 创建模拟日志目录

bash

复制代码
# 创建目录存放模拟的网站日志
mkdir -p /opt/module/flume/weblog

# 创建模拟日志文件
touch /opt/module/flume/weblog/pinduoduo_server.log

1.2 编写日志生成脚本

bash

复制代码
vim /opt/module/flume/weblog/generate_log.sh

粘贴以下内容:

bash

复制代码
#!/bin/bash

# 模拟用户IP池
IPS=("10.46.78.122" "192.168.1.100" "172.16.5.88" "10.0.0.55" "192.168.10.200")

# 模拟行为
ACTIONS=("login" "search" "click_product" "add_cart" "order" "logout")

# 无限循环,每5秒生成一条日志
while true; do
    # 当前时间
    TIME=$(date "+%Y-%m-%d %H:%M:%S")
    
    # 随机IP
    IP=${IPS[$RANDOM % ${#IPS[@]}]}
    
    # 随机行为
    ACTION=${ACTIONS[$RANDOM % ${#ACTIONS[@]}]}
    
    # 随机用户ID (1-1000)
    USER_ID=$((RANDOM % 1000 + 1))
    
    # 生成日志格式:时间 日志级别 IP 行为 用户ID
    echo "$TIME INFO $IP org.apache.xxx: user $USER_ID $ACTION"
    
    # 每5秒生成一条
    sleep 5
done

1.3 给脚本执行权限并运行

bash

复制代码
# 添加执行权限
chmod +x /opt/module/flume/weblog/generate_log.sh

# 后台运行脚本(持续产生日志)
cd /opt/module/flume/weblog
./generate_log.sh >> pinduoduo_server.log 2>&1 &

第二步:创建Flume采集配置(taildir版本)

2.1 创建Flume配置文件

bash

复制代码
vim /opt/module/flume/job/flume-weblog-hdfs.conf

粘贴以下内容:

properties

复制代码
# 模拟网站日志采集配置
a3.sources = r3
a3.sinks = k3
a3.channels = c3

# 使用taildir source(断点续传,不会丢数据)
a3.sources.r3.type = taildir
a3.sources.r3.positionFile = /opt/module/flume/taildir_position.json
a3.sources.r3.filegroups = f1
a3.sources.r3.filegroups.f1 = /opt/module/flume/weblog/pinduoduo_server.log
a3.sources.r3.batchSize = 100

# 输出到HDFS(按日期分区存储)
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://node100:9000/user/hive/warehouse/weblog_db/user_behavior_log/dt=%Y%m%d/
a3.sinks.k3.hdfs.filePrefix = weblog-
a3.sinks.k3.hdfs.round = true
a3.sinks.k3.hdfs.roundValue = 1
a3.sinks.k3.hdfs.roundUnit = hour
a3.sinks.k3.hdfs.useLocalTimeStamp = true
a3.sinks.k3.hdfs.batchSize = 100
a3.sinks.k3.hdfs.fileType = DataStream
a3.sinks.k3.hdfs.rollInterval = 60
a3.sinks.k3.hdfs.rollSize = 134217728
a3.sinks.k3.hdfs.rollCount = 0

# 内存Channel
a3.channels.c3.type = memory
a3.channels.c3.capacity = 10000
a3.channels.c3.transactionCapacity = 1000

# 绑定关系
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3

2.2 启动Flume采集

bash

复制代码
cd /opt/module/flume
bin/flume-ng agent -c conf/ -n a3 -f job/flume-weblog-hdfs.conf -Dflume.root.logger=INFO,console

保持这个终端运行,你会看到Flume在等待数据。


第三步:验证数据已经写入HDFS

3.1 等待1-2分钟让数据积累

bash

复制代码
# 新开一个终端,查看HDFS上的文件
hdfs dfs -ls /user/hive/warehouse/weblog_db/
hdfs dfs -ls /user/hive/warehouse/weblog_db/user_behavior_log/
hdfs dfs -ls /user/hive/warehouse/weblog_db/user_behavior_log/dt=$(date +%Y%m%d)/

# 查看具体内容
hdfs dfs -cat /user/hive/warehouse/weblog_db/user_behavior_log/dt=$(date +%Y%m%d)/weblog-* | head -20

你应该能看到类似这样的数据:

text

复制代码
2025-05-28 15:30:01 INFO 10.46.78.122 org.apache.xxx: user 345 login
2025-05-28 15:30:06 INFO 192.168.1.100 org.apache.xxx: user 789 search

第四步:Hive分析(完整SQL流程)

4.1 启动Hive

bash

复制代码
# 进入Hive安装目录
cd /opt/module/hive

# 启动Hive CLI
bin/hive

4.2 创建外部表(关联HDFS数据)

sql

复制代码
-- 创建数据库
CREATE DATABASE IF NOT EXISTS weblog_db;
USE weblog_db;

-- 创建外部表(分区表)
CREATE EXTERNAL TABLE user_behavior_log (
    log_time STRING COMMENT '日志时间',
    log_level STRING COMMENT '日志级别',
    user_ip STRING COMMENT '用户IP',
    message STRING COMMENT '日志消息'
)
PARTITIONED BY (dt STRING COMMENT '日期分区')
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
    "input.regex" = "([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) (\\S+) (\\S+) (.*)"
)
STORED AS TEXTFILE
LOCATION '/user/hive/warehouse/weblog_db/user_behavior_log';

4.3 加载分区数据

sql

复制代码
-- 方法1:手动添加分区
ALTER TABLE user_behavior_log ADD PARTITION (dt='20250528') LOCATION '/user/hive/warehouse/weblog_db/user_behavior_log/dt=20250528/';

-- 方法2:自动修复分区(推荐)
MSCK REPAIR TABLE user_behavior_log;

4.4 执行分析查询

sql

复制代码
-- 1. 查看数据总量
SELECT COUNT(*) FROM user_behavior_log;

-- 2. 按日期统计访问量(你笔记里要的效果)
SELECT 
    dt AS 日期,
    COUNT(1) AS 用户行为总数
FROM user_behavior_log
GROUP BY dt;

-- 3. 按行为类型统计
SELECT 
    REGEXP_EXTRACT(message, 'user (\\d+) (\\w+)', 2) AS 行为类型,
    COUNT(1) AS 次数
FROM user_behavior_log
GROUP BY REGEXP_EXTRACT(message, 'user (\\d+) (\\w+)', 2);

-- 4. Top10活跃用户
SELECT 
    REGEXP_EXTRACT(message, 'user (\\d+)', 1) AS 用户ID,
    COUNT(1) AS 活跃次数
FROM user_behavior_log
GROUP BY REGEXP_EXTRACT(message, 'user (\\d+)', 1)
ORDER BY 活跃次数 DESC
LIMIT 10;

-- 5. 按小时统计访问趋势
SELECT 
    HOUR(log_time) AS 小时,
    COUNT(1) AS 访问量
FROM user_behavior_log
WHERE dt = '20250528'
GROUP BY HOUR(log_time)
ORDER BY 小时;

第五步:完整的数据处理流程(你笔记最后的内容)

你笔记里写的这段:

bash

复制代码
hadoop fs -get hdfs日志文件 linux本地
awk -F " " '{print $1,$3,$7}' >> data.txt
load data local inpath data.txt into table 用户行为表;

对应的标准做法应该是:

5.1 直接从HDFS导出到本地

bash

复制代码
# 下载HDFS数据到本地
hdfs dfs -get /user/hive/warehouse/weblog_db/user_behavior_log/dt=20250528/* /tmp/weblog_data.txt

# 用awk提取需要的字段(时间、IP、行为)
awk '{print $1, $3, $7}' /tmp/weblog_data.txt > /tmp/analysis.txt

5.2 或者直接用Hive导出查询结果

sql

复制代码
-- Hive中直接导出查询结果到本地
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/hive_export'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
SELECT 
    log_time,
    user_ip,
    REGEXP_EXTRACT(message, 'user \\d+ (\\w+)', 1) AS action
FROM user_behavior_log
WHERE dt = '20250528';

🎯 你现在需要做什么

按顺序执行:

  1. 第一步:运行日志生成脚本(产生模拟数据)

  2. 第二步:启动Flume采集(看到数据在传输)

  3. 第三步:检查HDFS上是否有数据

  4. 第四步:进入Hive执行SQL查询

把每一步的执行结果截图或复制给我,我帮你确认是否正确。

如果有报错,直接把错误信息发给我,我帮你解决。


📝 补充:你笔记中的疑问解答

"Flume特性是流式处理"

→ 是的,Flume是实时流式处理,数据一产生就被采集,不需要等到第二天。

"离线vs实时"

→ 离线:处理昨天的历史数据(如Hive凌晨跑批)

→ 实时:数据产生后几秒内就能处理(如Flume→Kafka→Spark Streaming)

"启动Hadoop -- 默认启动zookeeper"

→ 这句不完全准确。Hadoop不需要ZK,但如果你要用HBase或Kafka才需要ZK。教学环境一般Hadoop单独运行即可。


zookeeper是什么?Kafka刚学完,后面马上要学习HBase


太好了!刚学完Kafka,马上学HBase,这时候理解ZooKeeper非常关键。


我用你刚学的Kafka作为桥梁,帮你理清ZooKeeper是什么。


🎯 ZooKeeper 一句话定义

ZooKeeper = 分布式系统的"管家" + "通知中心"

负责:协调管理配置维护命名服务集群管理


一、用Kafka理解ZooKeeper(你已经学过的)

Kafka中ZooKeeper的作用(你肯定见过)

bash

复制代码
# 启动Kafka时,必须指定ZooKeeper地址
bin/kafka-server-start.sh config/server.properties
# server.properties里写着:zookeeper.connect=localhost:2181

ZooKeeper为Kafka做了什么?

Kafka组件 ZooKeeper管理的内容
Broker 记录哪些Broker活着、挂了、是新加入的
Topic 记录Topic的元数据(分区数、副本数)
Partition Leader 选哪个Broker作为分区的Leader
Consumer Group 记录消费者组消费到哪个offset(旧版本)
Controller 从Broker中选出一个作为"总管"

通俗理解:

  • ZooKeeper = 班级花名册(记录每个同学在不在、座位在哪)

  • Kafka = 全班同学

  • 没有花名册 → 老师找不到学生,学生找不到自己的座位


二、ZooKeeper核心概念(最简单的理解)

2.1 数据结构:就像文件系统

text

复制代码
/ (根目录)
├── /kafka
│   ├── /brokers
│   │   ├── /ids/0  (Broker 0的信息)
│   │   ├── /ids/1  (Broker 1的信息)
│   │   └── /topics
│   │       ├── /user-log/partitions/0/state
│   │       └── /order-info/partitions/1/state
├── /hbase
│   ├── /master
│   ├── /region-server
│   └── /table
└── /myapp
    └── /config

每个节点叫Znode,可以存数据(如"10.0.0.1:9092"),也可以有子节点。

2.2 两大特性(面试必问)

特性 解释 例子(Kafka中)
临时节点 客户端断开连接,节点自动删除 Broker挂了 → 临时节点消失 → 其他Broker知道它下线了
Watch机制 节点变化时通知客户端 Broker 1挂了 → ZooKeeper通知所有订阅者 → Controller重新选Leader

三、ZooKeeper在Kafka vs HBase中的角色对比

你刚学完Kafka,马上学HBase,对比着看:

功能 Kafka中的ZK HBase中的ZK
选主 选举Controller Broker 选举HMaster(主节点)
服务发现 记录所有Broker地址 记录所有RegionServer地址
元数据存储 Topic/分区元数据 表元数据、Region位置
状态监控 Broker健康状态 RegionServer健康状态
分布式锁 保证同组内只有一个Consumer消费 保证同一时刻只有一个Master写入

关键区别:

  • Kafka 2.8+ 可以不用ZK(用了Raft协议自带的元数据管理)

  • HBase 必须依赖ZK(核心依赖,无法脱离)


四、实际操作:你现在应该做什么

4.1 检查ZooKeeper是否运行(教室环境)

bash

复制代码
# 查看ZK进程
jps | grep QuorumPeerMain

# 或者
ps aux | grep zookeeper

# 连接ZK看看
zkCli.sh -server node100:2181

4.2 ZK基础命令(帮你熟悉)

bash

复制代码
# 连接后执行
ls /                    # 查看根目录
ls /kafka               # 查看Kafka保存的信息(如果装了Kafka)
get /kafka/brokers/ids/0  # 查看Broker 0的信息
stat /                  # 查看节点状态
quit                    # 退出

4.3 创建自己的节点(练习)

bash

复制代码
create /myapp "hello"
get /myapp
set /myapp "world"
delete /myapp

五、HBase中ZK的作用(预习)

你马上要学的HBase,ZK负责:

text

复制代码
1. 保证只有一个HMaster运行(避免两个Master打架)
2. 监控RegionServer生死(谁挂了立刻通知Master)
3. 存储HBase系统元数据(-ROOT-表的位置)
4. 提供Master选举(主备切换)

启动顺序:

bash

复制代码
# 1. 先启动ZooKeeper(必须)
zkServer.sh start

# 2. 再启动HBase
start-hbase.sh

# 3. HMaster和RegionServer会自动向ZK注册

六、常见问题解答

Q1:为什么Kafka可以脱离ZK,HBase不行?

A: Kafka 2.8+实现了自己的Raft协议管理元数据。HBase的设计深度绑定ZK,替换成本太高。

Q2:教室环境需要单独启动ZK吗?

A: 看你们的配置:

bash

复制代码
# 检查是否开机自启
chkconfig --list | grep zookeeper

# 如果没有启动,手动启动
zkServer.sh start

# 或者有些环境用
systemctl start zookeeper

Q3:ZK挂了会怎样?

A:

  • Kafka: 生产消费不受影响(但无法做Broker上下线、分区重平衡)

  • HBase: 集群不可用(因为无法知道RegionServer状态)

Q4:生产环境ZK怎么部署?

A: 奇数台服务器(3/5/7台),因为选举需要过半同意:

  • 3台:允许1台挂

  • 5台:允许2台挂

  • 7台:允许3台挂


七、你现在可以做的练习

练习1:启动ZK并观察Kafka注册

bash

复制代码
# 1. 启动ZooKeeper
zkServer.sh start

# 2. 启动Kafka
bin/kafka-server-start.sh config/server.properties

# 3. 在另一个终端查看ZK中的数据
zkCli.sh
ls /kafka/brokers/ids   # 应该能看到你启动的Broker ID

练习2:模拟Broker下线

bash

复制代码
# 1. 在ZK中watch /kafka/brokers/ids
zkCli.sh
get /kafka/brokers/ids/0 watch

# 2. 停掉Kafka Broker
bin/kafka-server-stop.sh

# 3. 观察ZK终端的变化(临时节点消失)

📌 总结(一句话记忆)

ZooKeeper = 分布式系统的"通讯录"+"监控摄像头"

  • 通讯录:记录谁在哪、谁活着

  • 监控摄像头:谁变化了立刻通知所有人

对于你接下来的学习:

  1. Kafka:知道ZK管理Broker/Topic元数据即可

  2. HBase:必须掌握ZK的选举和监控机制(核心依赖)

  3. 面试重点:CAP理论中的CP(一致性+分区容错)


🎯 你现在告诉我

  1. 需要我帮你检查教室环境的ZK是否启动吗? (贴出jpszkCli.sh连接结果)

  2. 需要我用HBase的例子再详细解释ZK的选举机制吗?(结合你马上要学的内容)

  3. Flume的练习继续往下做吗?(之前模拟日志→HDFS→Hive已经跑通了吗?)

把当前进度和疑问发我,我接着帮你梳理!


因为是实操课,AI帮助我完成了实操,但我突然想起来,他遗漏了笔记中关于Flume的理论介绍部分,让我虽然实操通过了,但是完全不明白干了什么。于是有了下面的追问。

Flume也是今天第一天学,补充优化总结老师的课堂笔记中关于Flume的介绍


好的!我帮你把Flume课堂笔记重新梳理优化,让你今天学完后能真正理解并动手操作。


我会按**"是什么 → 为什么 → 怎么用 → 常见坑"**的逻辑重新组织。


📚 Flume 课堂笔记(优化版)


一、Flume是什么?(一句话 + 类比)

Flume = 日志界的"顺丰快递"

text

复制代码
数据源(网站日志)→ Flume → 目的地(HDFS/Kafka)
        实时采集      传输      存储

通俗理解:

  • 你网购下单 → 快递员上门取件 → 分拣中心 → 送到你家

  • 日志产生 → Source取数据 → Channel暂存 → Sink送走


二、为什么要用Flume?(解决什么问题)

问题 不用Flume 用Flume
数据源多 每个程序自己写代码写HDFS 统一配置,无需改代码
流量洪峰 直接把HDFS打崩 Channel做缓冲,削峰填谷
数据丢失 程序崩溃就丢数据 Channel支持持久化,重启续传
实时性 定时批处理(延迟高) 实时流式(秒级延迟)

核心价值: 解耦 + 缓冲 + 可靠 + 实时


三、Flume核心架构(3大组件)


整体结构图(务必记住)

text

bash 复制代码
[数据源] → [SOURCE] → [CHANNEL] → [SINK] → [目的地]
            ↑           ↑           ↑
         对接上游     缓冲区     对接下游

3.1 Source(数据来源)

职责: 对接上游数据源,读取数据封装成Event

常用Source类型:

类型 用法 场景 注意事项
taildir 监控文件追加内容 采集日志文件 ✅ 生产首选(支持断点续传)
netcat 监听端口 测试/演示 ❌ 生产不用(会丢数据)
exec 执行tail命令 简单场景 ⚠️ 进程重启会丢数据
http HTTP POST接收 埋点采集 适合Web端直接上报
kafka 从Kafka消费 数据管道 配合Kafka使用

3.2 Channel(传输通道)

职责: 缓冲区,解决读写速度不一致,保证数据不丢失

常用Channel类型:

类型 特点 场景 性能
memory 内存缓冲,快 允许丢数据(测试) 极高
file 磁盘缓冲,安全 生产环境(不能丢数据) 一般
kafka Kafka做通道 大数据管道

关键参数:

text

bash 复制代码
capacity = 1000           # 队列最大容量
transactionCapacity = 100 # 每次事务最大处理数

3.3 Sink(数据出口)

职责: 从Channel取数据,推送到目标系统

常用Sink类型:

类型 目的地 场景
hdfs HDFS 离线存储
kafka Kafka 消息队列
logger 控制台 测试调试
hbase HBase 实时查询
file_roll 本地文件 临时存储

四、核心概念:Event(事件)

Event = Flume传输的最小数据单元

text

bash 复制代码
┌─────────────────┐
│   Headers (KV)  │  ← 元数据(路径、时间戳等)
├─────────────────┤
│   Body (字节)    │  ← 实际数据(日志内容)
└─────────────────┘

例子:

json

复制代码
{
  "headers": {
    "timestamp": "2025-05-28 10:00:00",
    "filename": "app.log"
  },
  "body": "2025-05-28 10:00:01 INFO User login"
}

五、Flume配置文件详解(模板)

5.1 配置文件三段式结构

properties

复制代码
# 第1步:命名组件
agent名称.sources = source名称
agent名称.sinks = sink名称
agent名称.channels = channel名称

# 第2步:配置Source
agent名称.sources.source名称.type = xxx
agent名称.sources.source名称.参数1 = 值1

# 第3步:配置Sink
agent名称.sinks.sink名称.type = xxx
agent名称.sinks.sink名称.参数1 = 值1

# 第4步:配置Channel
agent名称.channels.channel名称.type = xxx
agent名称.channels.channel名称.参数1 = 值1

# 第5步:绑定关系
agent名称.sources.source名称.channels = channel名称
agent名称.sinks.sink名称.channel = channel名称

5.2 启动命令模板

bash

复制代码
bin/flume-ng agent \
  -c conf/ \                          # 配置文件目录
  -n agent名称 \                       # Agent名字(必须和配置一致)
  -f job/配置文件.conf \               # 配置文件路径
  -Dflume.root.logger=INFO,console   # 日志输出到控制台

六、三个实战案例(从易到难)

案例1:端口 → 控制台(测试连通性)

properties

复制代码
# netcat-logger.conf
a1.sources = r1
a1.sinks = k1
a1.channels = c1

a1.sources.r1.type = netcat
a1.sources.r1.bind = localhost
a1.sources.r1.port = 8888

a1.sinks.k1.type = logger

a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

测试:

bash

复制代码
# 终端1:启动Flume
bin/flume-ng agent -c conf/ -n a1 -f job/netcat-logger.conf

# 终端2:发送数据
nc localhost 8888
> hello flume

案例2:文件 → HDFS(生产常用)

properties

复制代码
# file-hdfs.conf
a2.sources = r2
a2.sinks = k2
a2.channels = c2

# Source: 监控文件
a2.sources.r2.type = exec
a2.sources.r2.command = tail -F /opt/logs/app.log

# Sink: 写入HDFS
a2.sinks.k2.type = hdfs
a2.sinks.k2.hdfs.path = hdfs://node100:9000/flume/%Y%m%d/%H
a2.sinks.k2.hdfs.filePrefix = logs-
a2.sinks.k2.hdfs.useLocalTimeStamp = true
a2.sinks.k2.hdfs.fileType = DataStream
a2.sinks.k2.hdfs.rollInterval = 60      # 1分钟滚动
a2.sinks.k2.hdfs.rollSize = 134217728   # 128M滚动

a2.channels.c2.type = memory
a2.channels.c2.capacity = 1000
a2.channels.c2.transactionCapacity = 100

a2.sources.r2.channels = c2
a2.sinks.k2.channel = c2

关键参数说明:

  • rollInterval:多久生成新文件(秒)

  • rollSize:文件多大时滚动(字节)

  • round:是否按时间创建文件夹

  • useLocalTimeStamp:使用本地时间(不用HDFS时间)


案例3:多路复用(一个Source → 多个Sink)

properties

复制代码
# fanout.conf
a3.sources = r3
a3.sinks = k3 k4
a3.channels = c3 c4

a3.sources.r3.type = taildir
a3.sources.r3.filegroups = f1
a3.sources.r3.filegroups.f1 = /opt/logs/*.log

# 根据header分流
a3.sources.r3.selector.type = multiplexing
a3.sources.r3.selector.header = logtype
a3.sources.r3.selector.mapping.error = c3
a3.sources.r3.selector.mapping.warn = c3
a3.sources.r3.selector.mapping.info = c4

# error/warn 写到HDFS
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://node100:9000/error_logs/

# info 写到Kafka
a3.sinks.k4.type = kafka
a3.sinks.k4.kafka.topic = weblog

a3.channels.c3.type = file
a3.channels.c4.type = memory

a3.sources.r3.channels = c3 c4
a3.sinks.k3.channel = c3
a3.sinks.k4.channel = c4

七、常见错误 & 解决方案

错误1:java.net.ConnectException: Connection refused

原因: HDFS没启动或地址写错

解决:

bash

复制代码
# 检查HDFS
hdfs dfs -ls /
# 查看配置
hdfs getconf -confKey fs.defaultFS

错误2:No such file or directory

原因: HDFS目录不存在

解决:

bash

复制代码
hdfs dfs -mkdir -p /flume

错误3:java.lang.OutOfMemoryError

原因: Channel容量太大

解决:

properties

复制代码
# 减小capacity
a1.channels.c1.capacity = 1000
# 增加JVM内存
export JAVA_OPTS="-Xmx2g"

错误4:Exec source丢数据

原因: 进程重启后tail命令中断

解决: 改用taildir source

properties

复制代码
a1.sources.r1.type = taildir
a1.sources.r1.positionFile = /opt/flume/taildir.json
a1.sources.r1.filegroups = f1
a1.sources.r1.filegroups.f1 = /opt/logs/*.log

八、面试重点(背下来)

8.1 Flume的三大组件及作用

  • Source:采集数据,封装Event

  • Channel:缓冲数据,保证可靠性

  • Sink:发送数据到目的地

8.2 Flume如何保证数据不丢失?

  • Channel支持file持久化(重启后数据还在)

  • Sink有事务机制(成功才删除Channel数据)

  • taildir source记录读取位置(断点续传)

8.3 Memory Channel和File Channel区别

维度 Memory File
速度
可靠性 低(进程死丢数据)
场景 测试/允许丢数据 生产/不能丢数据

8.4 Taildir Source优点

  • ✅ 支持断点续传

  • ✅ 支持通配符监控多个文件

  • ✅ 不会丢数据


九、你今天必须动手做的练习

练习1:跑通netcat示例

bash

复制代码
# 目标:看到Event输出

练习2:跑通file→HDFS示例

bash

复制代码
# 目标:HDFS上看到文件

练习3:修改参数观察效果

bash

复制代码
# 修改rollInterval=10,观察文件多久滚动一次
# 修改capacity=10,发送20条数据看会不会阻塞

练习4:模拟故障恢复

bash

复制代码
# 1. 启动taildir采集
# 2. 写入100条数据
# 3. Ctrl+C停掉Flume
# 4. 再写入50条
# 5. 重启Flume → 应该能从断点继续,不会重复消费前100条

十、你笔记中需要补充的地方

你的笔记 问题 补充
"基于流式架构" 没解释流式和离线的区别 流式:数据产生即处理(秒级); 离线:处理历史数据(T+1)
"高可用,高可靠" 没说明怎么实现的 高可用:多Agent部署; 高可靠:Channel持久化+事务
"taildir, http, exec" 没说明怎么选 生产用taildir, 测试用netcat, exec有坑别用
"实时将用户行为数据拉取到HDFS" 缺少具体配置 见上面案例2

🎯 你现在需要做的事

  1. 先确认环境jps 看Hadoop是否运行

  2. 跑通案例1(5分钟):netcat → logger

  3. 跑通案例2(10分钟):文件 → HDFS

  4. 把报错或成功截图发我

告诉我:

  • 哪个案例跑通了?

  • 哪个卡住了?

  • 报错信息是什么?

我帮你解决直到完全跑通!

相关推荐
WL_Aurora15 天前
Flume数据采集工具深度解析与实战配置
大数据·flume
jiajia_lisa23 天前
港澳及海外车牌识别的智能专家
flume
蓝眸少年CY2 个月前
Flume-使用与详解
大数据·flume
Gain_chance2 个月前
Flume01:大数据日志收集与传输利器
大数据·数据仓库·flume
小邓睡不饱耶2 个月前
Apache Flume 1.12.0 深度实战:从架构内核到企业级高可用部署(附完整代码案例)
架构·apache·flume
小邓睡不饱耶3 个月前
企业级日志采集实战:基于Flume的海量数据管道构建与优化
大数据·flume
程序员敲代码吗3 个月前
SparkCore算子详解:高效处理RDD的利器
flume
無森~4 个月前
Flume概述与基础
大数据·flume
WHD3064 个月前
苏州数据库(SQL Oracle)文件损坏修复
hadoop·sql·sqlite·flume·memcached