Flume学习笔记
——学习尚硅谷视频笔记
1、架构
1.1、Agent
一个Agent为一个JVM线程:由source,channel,sink三部分组成
1.2、source
用于收集数据,支持多种数据源
avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy。
1.3、channel
channel用于存储source传过来的数据,等待sink操作。Channel是线程安全的,可以同时处理几个Source的写入操作和几个Sink的读取操作。
分为:
- memory channel:基于内存的队列,如果flume宕机,会导致数据丢失 ,默认存100个event
- File Channel:基于文件,不会丢失数据 默认能存100万个event
1.4、sink
用于读取Channel中的数据并处理。
1.5、Event
用于传输数据的单元
2、组成详解
2.1、source
-
taildir source
-
支持断点续传,多目录配置。在Apache flume1.7之后产生的,如果是CDH,1.6之后就有了。之前可以使用自定义source去配置断点续传和多目录
-
taildir source挂了怎么办?
Flume不会丢失数据,但是有可能造成数据的重复,例如数据已经成功由Sink发出,但是没有接收到响应,Sink会再次发送数据,此时可能会导致数据的重复
Flume是不可能丢失数据的,其内部有完善的事务机制。 Source到Channel是事务性的, Channel到Sink是事务性的, 因此这两个环节不会出现数据的丢失, 唯一可能丢失数据的情况是Channel采用memoryChannel,agent宕机导致数据丢失, 或者Channel存储数据已满,导致Source不再写入,未写入的数据丢失。
-
重复数据怎么处理
-
不处理
-
处理:
-
自身处理:自定义source实现事务,额外增加了运算量(flume宕机可能很久才遇到一次,一次也就一两百条数据重复,如果自定义source,则对每条数据都要进行处理,得不偿失)
-
下一级处理:hive数仓里面处理(dwd层,数据清洗ETL) spark Streaming里面处理。去重手段:group by (id) ,开窗(id),只要窗口第一条
-
是否支持递归读取文件
不支持。需要自定义tail source(递归+读取)
消费Kafka+上传hdfs
-
-
-
2.2、channe
- FIle Channel:基于磁盘、效率低、可靠性高
- memoryChannel:基于内存,效率高、可靠性低
- KafkaChannel:数据存储在Kafka里面,基于磁盘、效率高于memoryChannel+Kafka,省了sink。flume1.6时,这个选项不起作用,1.7之后解决bug,才被广泛使用
- channel的选择:
- 下一级是Kafka,优先选择kafkaChannel
- 如果是别的,更关心可靠性的用File Channel,更关心性能使用MemoryChannel
2.3、 sink
2.3.1、hdfs sink
控制小文件:修改对应的启动配置文件
官方默认的这三个参数配置写入HDFS后会产生小文件,
hdfs.rollInterval、hdfs.rollSize、hdfs.rollCount
基于以上
hdfs.rollInterval=3600,
hdfs.rollSize=134217728,
hdfs.rollCount =0,
hdfs.roundValue=3600,
hdfs.roundUnit= second
几个参数综合作用,效果如下:
(1)tmp文件在达到128M时会滚动生成正式文件
(2)tmp文件创建超3600秒时会滚动生成正式文件
举例:在2018-01-01 05:23的时侯sink接收到数据,那会产生如下tmp文件:
/atguigu/20180101/atguigu.201801010520.tmp
即使文件内容没有达到128M,也会在06:23时滚动生成正式文件
-
压缩
开启压缩流;指定压缩编码方式(lzop/snappy)
3、案例
3.1、监控hive日志,并上传到hdfs
-
环境准备
确认Hadoop、Java环境变量无误
-
创建 flume-file-hdfs.conf 文件
#Name the components on this agent a2.sources = r2 a2.channels = c2 a2.sinks = k2 #Describe/configure the source #exec表示使用linux 命令 a2.sources.r2.type = exec a2.sources.r2.command = tail -F /tmp/lcq/hive.log a2.sources.r2.shell = /bin/bash -c #Describe the sink a2.sinks.k2.type = hdfs a2.sinks.k2.hdfs.path = hdfs://hadoop102:8020/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 #多久生成一个新的文件(s) a2.sinks.k2.hdfs.rollInterval = 60 #设置每个文件的滚动大小(128M) a2.sinks.k2.hdfs.rollSize = 134217700 #设置文件的滚动与event数量无关 a2.sinks.k2.hdfs.rollCount = 0 #Use a channel which buffers events in memory #channel类型为memory channel a2.channels.c2.type = memory #表示总容量为1000个event a2.channels.c2.capacity = 1000 #达到100个event再提交 a2.channels.c2.transactionCapacity = 100 #Bind the source and sink to the channel #将r2和channel连接起来 a2.sources.r2.channels = c2 #k2连接 a2.sinks.k2.channel = c2
-
注意:
对于所有与时间相关的转义序列,Event Header中必须存在以 “timestamp”的key(除非hdfs.useLocalTimeStamp设置为true,此方法会使用TimestampInterceptor自动添加timestamp)。
a3.sinks.k3.hdfs.useLocalTimeStamp = true
-
运行flume
$FLUME_HOME/bin/flume-ng agent --name a2 --conf conf/ --conf-file conf/file-flume-hdfs.conf
-
开启Hadoop和hive,操作hive产生日志
下面命令为我已经封装好的Hadoop启动脚本 [lcq@hadoop102 ~]$ start.sh [lcq@hadoop102 hive]$ bin/hive hive (default)>
-
进hdfs查看
-
注意各个地址别写错
3.2、实时监控目录下的多个文件,并上传到hdfs
spooldir source:Spooldir Source适合用于同步新文件,但不适合对实时追加日志的文件进行监听并同步;
3.2.1、创建配置文件
dir-flume-hdfs.conf
a3.sources = r3
a3.sinks = k3
a3.channels = c3
#Configure the source
a3.sources.r3.type = spooldir
a3.sources.r3.spoolDir = /opt/module/flume/test
a3.sources.r3.fileSuffix = .COMPLETED
a3.sources.r3.fileHeader = true
#忽略所有以.tmp结尾的文件,不上传
a3.sources.r3.ignorePattern = ([^ ]*\.tmp)
#configure the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://hadoop102:8020/flume/test/%Y%m%d/%H
#上传文件的前缀
a3.sinks.k3.hdfs.filePrefix = test-
#是否按照时间滚动文件夹
a3.sinks.k3.hdfs.round = true
#多少时间单位创建一个新的文件夹
a3.sinks.k3.hdfs.roundValue = 1
#重新定义时间单位
a3.sinks.k3.hdfs.roundUnit = hour
#是否使用本地时间戳
a3.sinks.k3.hdfs.useLocalTimeStamp = true
#积攒多少个event才flush到hdfs一次
a3.sinks.k3.hdfs.batchSize = 100
#设置文件类型,可支持压缩
a3.sinks.k3.hdfs.fileType = DataStream
#多久生成一个新的文件
a3.sinks.k3.hdfs.rollInterval = 60
#设置每个文件的滚动大小大概是128M
a3.sinks.k3.hdfs.rollSize = 134217700
#文件的滚动与Event数量无关
a3.sinks.k3.hdfs.rollCount = 0
# Configure channel
a3.channels.c3.type = memory
a3.channels.c3.capacity = 1000
a3.channels.c3.transactionCapacity = 100
# Bind the source and sink to the channel
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3
3.3.2、启动命令
[lcq@hadoop102 flume]$ bin/flume-ng agent --conf conf/ --name a3 --conf-file /job/dir-flume-hdfs.conf
3.2.3、创建test文件夹,并添加一些文件
3.2.4、去hdfs查看
3.2.5、再次查看test目录
会看到上传完成的文件的后缀会发生改变
3.3、实时监控目录下的多个追加文件
Taildir Source适合用于监听多个实施追加的文件,并且能够实现断点续传
3.3.1、需求
使用Flume监听整个目录的实时追加文件,并上传到hdfs
3.3.2、创建 taildir-flume-hdfs.conf
a3.sources = r3
a3.sinks = k3
a3.channels = c3
#configure the source
a3.sources.r3.type = TAILDIR
a3.sources.r3.positionFile = /opt/module/flume/tail_dir.json
a3.sources.r3.filegroups = f1 f2
a3.sources.r3.filegroups.f1 = /opt/module/flume/files/.*file.*
a3.sources.r3.filegroups.f2 = /opt/module/flume/files/.*log.*
#configure the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://hadoop102:8020/flume/test2/%Y%m%d/%H
#上传文件的前缀
a3.sinks.k3.hdfs.filePrefix = test-
#是否按照时间滚动文件夹
a3.sinks.k3.hdfs.round = true
#多少时间单位创建一个新的文件夹
a3.sinks.k3.hdfs.roundValue = 1
#重新定义时间单位
a3.sinks.k3.hdfs.roundUnit = hour
#是否使用本地时间戳
a3.sinks.k3.hdfs.useLocalTimeStamp = true
#积攒多少个Event才flush到HDFS一次
a3.sinks.k3.hdfs.batchSize = 100
#设置文件类型,可支持压缩
a3.sinks.k3.hdfs.fileType = DataStream
#多久生成一个新的文件
a3.sinks.k3.hdfs.rollInterval = 60
#设置每个文件的滚动大小大概是128M
a3.sinks.k3.hdfs.rollSize = 134217700
#文件的滚动与Event数量无关
a3.sinks.k3.hdfs.rollCount = 0
#configure the channel
a3.channels.c3.type = memory
a3.channels.c3.capacity = 1000
a3.channels.c3.transactionCapacity = 100
# Bind the source and sink to the channel
a3.sources.r3.channels = c3
a3.sinks.k3.channel = c3
3.3.3、启动命令
[lcq@hadoop102 flume]$ bin/flume-ng agent --name a3 --conf conf/ --conf-file /job/taildir-flume-hdfs.conf
3.3.4、创建files目录
3.3.5、添加文件
echo hahah >> file1.txt
3.3.6、去hdfs查看,并查看tail_dir.json
Taildir Source维护了一个json格式的position File,其会定期的往position File中更新每个文件读取到的最新的位置,因此能够实现断点续传。Position File的格式如下:
[lcq@hadoop102 flume]$ cat tail_dir.json
[{"inode":34672037,"pos":25,"file":"/opt/module/flume/files/file1.txt"},{"inode":34672039,"pos":5,"file":"/opt/module/flume/files/file2.txt"},{"inode":34672040,"pos":6,"file":"/opt/module/flume/files/file.file"}][lcq@hadoop102 flume]$
注:Linux中储存文件元数据的区域就叫做inode,每个inode都有一个号码,操作系统用inode号码来识别不同的文件,Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。
4、事务
4.1、source -> channel
Put事务
4.2、channel -> sink
take事务
这两个过程都是事务性的,不会丢失数据,但是如果channel采用memory channel,如果系统宕机,有可能会产生数据丢失
Flume不会丢失数据,但是有可能产生数据重复,sink发出数据,但是没有收到回复,Sink会在此发送数据,造成数据重复
5、拦截器、选择器、监控器
5.1、拦截器
(1)、用途
1、区分数据类型:启动日志,事件日志
2、初步数据清洗:判断数据完整(json)
(2)、自定义拦截器步骤
拦截器要不要看需求
1、定义一个类,实现interceptor接口
2、重写四个方法:初始化,关闭,单event,多event
3、创建一个静态内部类Builder
5.2、选择器
1、rep:默认选择器,会发往所有下一级通道
2、mul:选择性发
5.3、监控器
ganglia
如果尝试提交的次数,远远大于最终提交成功的次数,说明flume性能不行
解决方法:
1、提高内存,4-6G flume_env.sh
2、增加flume台数 服务器配置(16g/32g 8T)