大数据组件笔记 -- Flume

一、入门

Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。Flume基于流式架构,灵活简单。

  • 为什么使用 Flume

Flume最主要的作用就是,实时读取服务器本地磁盘的数据,将数据写入到HDFS。

在这里插入图片描述

1.1 基础架构

在这里插入图片描述

  • Agent
  1. Agent是一个JVM进程,它以事件的形式将数据从源头送至目的。
  2. Agent主要有3个部分组成,Source、Channel、Sink。
  • Source
  1. Source是负责接收数据到Flume Agent的组件。
  2. Source组件可以处理各种类型、各种格式的日志数据,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy。
  • Sink
  1. Sink不断地轮询Channel中的事件且批量地移除它们,并将这些事件批量写入到存储或索引系统、或者被发送到另一个Flume Agent。
  2. Sink组件目的地包括hdfs、logger、avro、thrift、ipc、file、HBase、solr、自定义。
  • Channel
  1. Channel是位于Source和Sink之间的缓冲区。因此,Channel允许Source和Sink运作在不同的速率上。
  2. Channel是线程安全的,可以同时处理几个Source的写入操作和几个Sink的读取操作。
  3. Flume自带两种Channel:Memory Channel和File Channel。
  4. Memory Channel 是内存中的队列。Memory Channel在不需要关心数据丢失的情景下适用。如果需要关心数据丢失,那么Memory Channel就不应该使用,因为程序死亡、机器宕机或者重启都会导致数据丢失。
  5. File Channel 将所有事件写到磁盘。因此在程序关闭或机器宕机的情况下不会丢失数据。
  • Event
  1. 传输单元,Flume数据传输的基本单元,以Event的形式将数据从源头送至目的地。
  2. Event由Header和Body两部分组成,Header用来存放该event的一些属性,为K-V结构,Body用来存放该条数据,形式为字节数组。

在这里插入图片描述

1.2 安装部署

  • 解压缩
[omm@bigdata01 soft]$ pwd
/opt/soft
[omm@bigdata01 soft]$ ll | grep flume
-rw-rw-r--  1 omm  omm   67938106 Mar  7 21:09 apache-flume-1.9.0-bin.tar.gz
[omm@bigdata01 soft]$ tar -zxf apache-flume-1.9.0-bin.tar.gz -C /opt/module/
[omm@bigdata01 soft]$ ln -s /opt/module/apache-flume-1.9.0-bin /opt/module/flume
[omm@bigdata01 soft]$ cd /opt/module/flume/
[omm@bigdata01 flume]$ rm lib/guava-11.0.2.jar # 兼容Hadoop中的Jar包
[omm@bigdata01 flume]$ 
  • 配置环境变量
[omm@bigdata01 ~]$ sudo vi /etc/profile
[omm@bigdata01 ~]$ tail -3 /etc/profile
# Flume
export FLUME_HOME=/opt/module/flume
export PATH=$PATH:$FLUME_HOME/bin
[omm@bigdata01 ~]$ source /etc/profile
[omm@bigdata01 ~]$ 

1.3 监控端口数据官方案例

使用Flume监听一个端口,收集该端口数据,并打印到控制台。

  • 编写配置文件
[omm@bigdata01 flume]$ pwd
/opt/module/flume
[omm@bigdata01 flume]$ mkdir job
[omm@bigdata01 flume]$ cd job/
[omm@bigdata01 job]$ vim flume-netcat-logger.conf
[omm@bigdata01 job]$ cat flume-netcat-logger.conf
# Name the components on this agent, seperate by space.
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata01
a1.sources.r1.port = 44444

# 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
[omm@bigdata01 job]$ 
  • 启动任务
[omm@bigdata01 ~]$ flume-ng agent --name a1 \  # agent name
--conf /opt/module/flume/conf/ \ # flume conf dir
--conf-file /opt/module/flume/job/flume-netcat-logger.conf \ # job conf file
-Dflume.root.logger=INFO,console # log level and target
  1. 测试

在这里插入图片描述

1.4 实时监控单个追加文件写入日志

实时监控Hive日志,并写入到Flume日志中。

  1. 修改日志配置文件,将日志输出到文件
[omm@bigdata01 conf]$ pwd
/opt/module/flume/conf
[omm@bigdata01 conf]$ vi log4j.properties 
[omm@bigdata01 conf]$ grep /opt/module/flume/logs log4j.properties 
flume.log.dir=/opt/module/flume/logs/
[omm@bigdata01 conf]$ 
  1. 运行,不加 -Dflume.root.logger=INFO,console
# 不加 -Dflume.root.logger=INFO,console
[omm@bigdata01 logs]$ flume-ng agent --name a1  --conf /opt/module/flume/conf/  --conf-file /opt/module/flume/job/flume-netcat-logger.conf
[omm@bigdata01 logs]$ pwd
/opt/module/flume/logs
[omm@bigdata01 logs]$ grep 20150614 flume.log 
08 Mar 2021 19:32:56,437 INFO  [SinkRunner-PollingRunner-DefaultSinkProcessor] (org.apache.flume.sink.LoggerSink.process:95)  - Event: { headers:{} body: 32 30 31 35 30 36 31 34                         20150614 }
[omm@bigdata01 logs]$ grep rayslee flume.log 
08 Mar 2021 19:32:57,688 INFO  [SinkRunner-PollingRunner-DefaultSinkProcessor] (org.apache.flume.sink.LoggerSink.process:95)  - Event: { headers:{} body: 72 61 79 73 6C 65 65                            rayslee }
[omm@bigdata01 logs]$ 

1.5 实时监控单个追加文件写入 HDFS

实时监控Hive日志,并上传到HDFS中。

在这里插入图片描述

[omm@bigdata01 job]$ pwd
/opt/module/flume/job
[omm@bigdata01 job]$ vi logfile-flume-hdfs.conf 
[omm@bigdata01 job]$ cat logfile-flume-hdfs.conf 
# 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/logs/messages
a2.sources.r2.shell = /bin/bash -c

# Describe the sink
a2.sinks.k2.type = hdfs
a2.sinks.k2.hdfs.path = hdfs://bigdata01:8020/flume/%Y%m%d/%H
#上传文件的前缀
a2.sinks.k2.hdfs.filePrefix = messages-
#是否按照时间滚动文件夹
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
[omm@bigdata01 job]$ 
[omm@bigdata01 job]$ flume-ng agent -n a2 -c ../conf/ -f logfile-flume-hdfs.conf
[omm@bigdata01 logs]$ echo "This is a test." >> messages.log

在这里插入图片描述

1.6 实时监控目录下多个新文件

使用Flume监听整个目录的文件,并上传至HDFS。

在这里插入图片描述

[omm@bigdata01 job]$ vi flume-dir-hdfs.conf
[omm@bigdata01 job]$ cat flume-dir-hdfs.conf 
a3.sources = r3
a3.sinks = k3
a3.channels = c3

# Describe/configure the source
a3.sources.r3.type = spooldir
a3.sources.r3.spoolDir = /opt/module/flume/logs/upload
a3.sources.r3.fileSuffix = .COMPLETED
a3.sources.r3.fileHeader = true
#忽略所有以.tmp结尾的文件,不上传
a3.sources.r3.ignorePattern = ([^ ]*\.tmp)

# Describe the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://bigdata01:8020/flume/upload/%Y%m%d/%H
#上传文件的前缀
a3.sinks.k3.hdfs.filePrefix = upload-
#是否按照时间滚动文件夹
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

# Use a channel which buffers events in memory
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
[omm@bigdata01 job]$ 

[omm@bigdata01 job]$ flume-ng agent -n a3 -c ../conf/ -f flume-dir-hdfs.conf
[omm@bigdata01 logs]$ mkdir upload
[omm@bigdata01 logs]$ echo "This is test 1." >> upload/test1.log
[omm@bigdata01 logs]$ echo "This is test 2." >> upload/test2.log
[omm@bigdata01 logs]$ ll upload/
total 8
-rw-rw-r-- 1 omm omm 16 Mar  9 20:43 test1.log.COMPLETED
-rw-rw-r-- 1 omm omm 16 Mar  9 20:43 test2.log.COMPLETED
[omm@bigdata01 logs]$ 

在这里插入图片描述

1.7 实时监控目录下的多个追加文件

  • 断点续传
  1. Exec source适用于监控一个实时追加的文件,不能实现断点续传;
  2. Spooldir Source适合用于同步新文件,但不适合对实时追加日志的文件进行监听并同步;
  3. 而Taildir Source适合用于监听多个实时追加的文件,并且能够实现断点续传。

使用Flume监听整个目录的实时追加文件,并上传至HDFS。

在这里插入图片描述

[omm@bigdata01 job]$ vi flume-taildir-hdfs.conf
[omm@bigdata01 job]$ cat flume-taildir-hdfs.conf 
a3.sources = r3
a3.sinks = k3
a3.channels = c3

# Describe/configure the source
a3.sources.r3.type = TAILDIR
a3.sources.r3.positionFile = /opt/module/flume/logs/files/tail_dir.json
a3.sources.r3.filegroups = f1 f2
a3.sources.r3.filegroups.f1 = /opt/module/flume/logs/files/.*file.*
a3.sources.r3.filegroups.f2 = /opt/module/flume/logs/files/.*log.*

# Describe the sink
a3.sinks.k3.type = hdfs
a3.sinks.k3.hdfs.path = hdfs://bigdata01:8020/flume/upload2/%Y%m%d/%H
#上传文件的前缀
a3.sinks.k3.hdfs.filePrefix = upload-
#是否按照时间滚动文件夹
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

# Use a channel which buffers events in memory
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
[omm@bigdata01 job]$ 
[omm@bigdata01 job]$ flume-ng agent -n a3 -c ../conf/ -f flume-taildir-hdfs.conf 
[omm@bigdata01 logs]$ ll files/
total 0
-rw-rw-r-- 1 omm omm 0 Mar  9 20:47 tail_dir.json
[omm@bigdata01 logs]$ echo "This is test log" > files/test.log
[omm@bigdata01 logs]$ echo "This is test file" > files/test.file

在这里插入图片描述

二、进阶

2.1 Flume 事务

在这里插入图片描述

  • Put事务流程
  1. doPut:将批数据先写入临时缓冲区putList
  2. doCommit:检查channel内存队列是否足够合并。
  3. doRollback:channel内存队列空间不足,回滚数据
  • Take事务
  1. doTake:将数据取到临时缓冲区takeList,并将数据发送到HDFS
  2. doCommit:如果数据全部发送成功,则清除临时缓冲区takeList
  3. doRollback:数据发送过程中如果出现异常,rollback将临时缓冲区takeList中的数据归还给channel内存队列。

2.2 Flume Agent内部原理

在这里插入图片描述

  • ChannelSelector
  1. ChannelSelector的作用就是选出Event将要被发往哪个Channel。其共有两种类型,分别是Replicating(复制)和Multiplexing(多路复用)。
  2. ReplicatingSelector会将同一个Event发往所有的Channel,Multiplexing会根据相应的原则,将不同的Event发往不同的Channel。
  • SinkProcessor
  1. SinkProcessor共有三种类型,分别是DefaultSinkProcessorLoadBalancingSinkProcessor和FailoverSinkProcessor
  2. DefaultSinkProcessor对应的是单个的Sink,LoadBalancingSinkProcessor和FailoverSinkProcessor对应的是Sink Group,LoadBalancingSinkProcessor可以实现负载均衡的功能,FailoverSinkProcessor可以错误恢复的功能。

2.3 Flume拓扑结构

2.3.1 简单串联

在这里插入图片描述

  1. 这种模式是将多个flume顺序连接起来了,从最初的source开始到最终sink传送的目的存储系统。
  2. 此模式不建议桥接过多的flume数量, flume数量过多不仅会影响传输速率,而且一旦传输过程中某个节点flume宕机,会影响整个传输系统。

2.3.2 复制和多路复用

在这里插入图片描述

  1. Flume支持将事件流向一个或者多个目的地。
  2. 这种模式可以将相同数据复制到多个channel中,或者将不同数据分发到不同的channel中,sink可以选择传送到不同的目的地。

2.3.3 负载均衡和故障转移

Flume支持使用将多个sink逻辑上分到一个sink组,sink组配合不同的SinkProcessor可以实现负载均衡和错误恢复的功能。

在这里插入图片描述

2.3.4 聚合

在这里插入图片描述

  1. 这种模式是我们最常见的,也非常实用,日常web应用通常分布在上百个服务器,大者甚至上千个、上万个服务器。
  2. 产生的日志,处理起来也非常麻烦,用flume的这种组合方式能很好的解决这一问题。
  3. 每台服务器部署一个flume采集日志,传送到一个集中收集日志的flume,再由此flume上传到hdfs、hive、hbase等,进行日志分析。

2.4 演示:串联

在这里插入图片描述

[omm@bigdata01 job]$ vi netcatsource_avrosink.conf
[omm@bigdata01 job]$ cat netcatsource_avrosink.conf
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata01
a1.sources.r1.port = 22222

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

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata02
a1.sinks.k1.port = 33333

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata01 job]$ 
[omm@bigdata02 job]$ vi avrosource_loggersink.conf
[omm@bigdata02 job]$ cat avrosource_loggersink.conf
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata02
a1.sources.r1.port = 33333

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

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata02 job]$ 
[omm@bigdata02 job]$ flume-ng agent -n a1 -c ../conf/ -f avrosource_loggersink.conf
[omm@bigdata01 job]$ flume-ng agent -n a1 -c ../conf/ -f netcatsource_avrosink.conf -Dflume.root.logger=INFO,console
[omm@bigdata01 logs]$ nc bigdata01 22222
Can-U-Hear-Me?
OK
[omm@bigdata02 logs]$ grep Can-U-Hear-Me? flume.log 
09 Mar 2021 21:58:55,040 INFO  [SinkRunner-PollingRunner-DefaultSinkProcessor] (org.apache.flume.sink.LoggerSink.process:95)  - Event: { headers:{} body: 43 61 6E 2D 55 2D 48 65 61 72 2D 4D 65 3F       Can-U-Hear-Me? }
[omm@bigdata02 logs]$ 

2.5 演示:复制

在这里插入图片描述

[omm@bigdata01 job]$ vi source_selector_replication.conf
[omm@bigdata01 job]$ cat source_selector_replication.conf
a1.sources = r1
a1.channels = c1 c2
a1.sinks = k1 k2

a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /opt/module/flume/logs/copy.log
# 当同个source对应多个channel的时候,可以配置channel selector 决定怎么发
# 默认为 replacating, 即复制发送到每个channel

a1.channels.c1.type = memory
a1.channels.c2.type = memory

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata02
a1.sinks.k1.port = 22222
a1.sinks.k2.type = avro
a1.sinks.k2.hostname = bigdata03
a1.sinks.k2.port = 33333

a1.sources.r1.channels = c1 c2
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c2
[omm@bigdata01 job]$ 
[omm@bigdata02 job]$ vi source_selector_replication.conf
[omm@bigdata02 job]$ cat source_selector_replication.conf
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata02
a1.sources.r1.port = 22222

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata02 job]$ flume-ng agent -n a1 -c ../conf/ -f source_selector_replication.conf -Dflume.root.logger=INFO,console
[omm@bigdata03 job]$ vi source_selector_replication.conf
[omm@bigdata03 job]$ cat source_selector_replication.conf
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata03
a1.sources.r1.port = 33333

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata03 job]$ flume-ng agent -n a1 -c ../conf/ -f source_selector_replication.conf -Dflume.root.logger=INFO,console
[omm@bigdata01 job]$ flume-ng agent -n a1 -c ../conf/ -f source_selector_replication.conf -Dflume.root.logger=INFO,console
[omm@bigdata01 logs]$ echo "TODAY-AND-YOU" >> copy.log

在这里插入图片描述

2.6 演示:多路复用(分发)

通过判断源 event 中的数据,决定发往哪一个 channel 。

[omm@bigdata01 job]$ vi multiplexing.conf 
[omm@bigdata01 job]$ cat multiplexing.conf 
a1.sources = r1
a1.channels = c1 c2
a1.sinks = k1 k2

a1.sources.r1.type = exec
a1.sources.r1.command = tail -F /opt/module/flume/logs/multiplexing.log

# --- multiplexing
a1.sources.r1.selector.type = multiplexing
# --- measure based on headers key named 'state'
a1.sources.r1.selector.header = state
# --- send event to c1 when state is CZ
a1.sources.r1.selector.mapping.CZ = c1
# --- send event to c2 when state is US
a1.sources.r1.selector.mapping.US = c2

# --- add KV to headers by interceptor
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = static
a1.sources.r1.interceptors.i1.key = state
a1.sources.r1.interceptors.i1.value = CZ

a1.channels.c1.type = memory
a1.channels.c2.type = memory

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata02
a1.sinks.k1.port = 22222
a1.sinks.k2.type = avro
a1.sinks.k2.hostname = bigdata03
a1.sinks.k2.port = 33333

a1.sources.r1.channels = c1 c2
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c2
[omm@bigdata01 job]$ 
[omm@bigdata02 job]$ vi multiplexing.conf 
[omm@bigdata02 job]$ cat multiplexing.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata02
a1.sources.r1.port = 22222

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata02 job]$ flume-ng agent -n a1 -c ../conf/ -f multiplexing.conf -Dflume.root.logger=INFO,console
[omm@bigdata03 job]$ vi multiplexing.conf 
[omm@bigdata03 job]$ cat multiplexing.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata03
a1.sources.r1.port = 33333

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata03 job]$ flume-ng agent -n a1 -c ../conf/ -f multiplexing.conf -Dflume.root.logger=INFO,console
[omm@bigdata01 job]$ flume-ng agent -n a1 -c ../conf/ -f multiplexing.conf -Dflume.root.logger=INFO,console

在这里插入图片描述

2.7 演示:故障转移

[omm@bigdata01 job]$ vi failover.conf 
[omm@bigdata01 job]$ cat failover.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1 k2

a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata01
a1.sources.r1.port = 11111

a1.channels.c1.type = memory

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata02
a1.sinks.k1.port = 22222

a1.sinks.k2.type = avro
a1.sinks.k2.hostname = bigdata03
a1.sinks.k2.port = 33333

# one channel with multi sinks should tell sink-processor
a1.sinkgroups = g1
a1.sinkgroups.g1.sinks = k1 k2
a1.sinkgroups.g1.processor.type = failover
a1.sinkgroups.g1.processor.priority.k1 = 5
a1.sinkgroups.g1.processor.priority.k2 = 10

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c1
[omm@bigdata01 job]$ flume-ng agent -n a1 -c ../conf/ -f failover.conf -Dflume.root.logger=INFO,console
[omm@bigdata02 job]$ vi failover.conf 
[omm@bigdata02 job]$ cat failover.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata02
a1.sources.r1.port = 22222

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata02 job]$ flume-ng agent -n a1 -c ../conf/ -f failover.conf -Dflume.root.logger=INFO,console
[omm@bigdata03 job]$ vi failover.conf 
[omm@bigdata03 job]$ cat failover.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata03
a1.sources.r1.port = 33333

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata03 job]$ flume-ng agent -n a1 -c ../conf/ -f failover.conf -Dflume.root.logger=INFO,console

在这里插入图片描述

2.8 演示:负载均衡

[omm@bigdata01 job]$ vi load-balance.conf 
[omm@bigdata01 job]$ cat load-balance.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1 k2

a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata01
a1.sources.r1.port = 11111

a1.channels.c1.type = memory

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata02
a1.sinks.k1.port = 22222

a1.sinks.k2.type = avro
a1.sinks.k2.hostname = bigdata03
a1.sinks.k2.port = 33333

# one channel with multi sinks should tell sink-processor
a1.sinkgroups = g1
a1.sinkgroups.g1.sinks = k1 k2
a1.sinkgroups.g1.processor.type = load_balance
a1.sinkgroups.g1.processor.selector = random

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c1
[omm@bigdata01 job]$ flume-ng agent -n a1 -c ../conf/ -f load-balance.conf -Dflume.root.logger=INFO,console
[omm@bigdata02 job]$ vi load-balance.conf 
[omm@bigdata02 job]$ cat load-balance.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata02
a1.sources.r1.port = 22222

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata02 job]$ flume-ng agent -n a1 -c ../conf/ -f load-balance.conf -Dflume.root.logger=INFO,console
[omm@bigdata03 job]$ vi load-balance.conf 
[omm@bigdata03 job]$ cat load-balance.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata03
a1.sources.r1.port = 33333

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata03 job]$ flume-ng agent -n a1 -c ../conf/ -f load-balance.conf -Dflume.root.logger=INFO,console

在这里插入图片描述

2.9 演示:聚合

[omm@bigdata01 job]$ vi aggregation.conf 
[omm@bigdata01 job]$ cat aggregation.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata01
a1.sources.r1.port = 11111

a1.channels.c1.type = memory

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata03
a1.sinks.k1.port = 33333

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata01 job]$ flume-ng agent -n a1 -c ../conf/ -f aggregation.conf -Dflume.root.logger=INFO,console
[omm@bigdata02 job]$ vi aggregation.conf
[omm@bigdata02 job]$ cat aggregation.conf
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata02
a1.sources.r1.port = 22222

a1.channels.c1.type = memory

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata03
a1.sinks.k1.port = 33333

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata02 job]$ flume-ng agent -n a1 -c ../conf/ -f aggregation.conf -Dflume.root.logger=INFO,console
[omm@bigdata03 job]$ vi aggregation.conf
[omm@bigdata03 job]$ cat aggregation.conf
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata03
a1.sources.r1.port = 33333

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata03 job]$ flume-ng agent -n a1 -c ../conf/ -f aggregation.conf -Dflume.root.logger=INFO,console

在这里插入图片描述

三、客制化

3.1 自定义Interceptor

案例需求:使用Flume采集服务器本地日志,需要按照日志类型的不同,将不同种类的日志发往不同的分析系统。

  • 需求分析
  1. 在实际的开发中,一台服务器产生的日志类型可能有很多种,不同类型的日志可能需要发送到不同的分析系统。
  2. 此时会用到Flume拓扑结构中的Multiplexing结构,Multiplexing的原理是,根据event中Header的某个key的值,将不同的event发送到不同的Channel中,所以我们需要自定义一个Interceptor,为不同类型的event的Header中的key赋予不同的值。
  3. 在该案例中,我们以端口数据模拟日志,以数字(单个)和字母(单个)模拟不同类型的日志,我们需要自定义interceptor区分数字和字母,将其分别发往不同的分析系统(Channel)。

在这里插入图片描述

<dependency>
    <groupId>org.apache.flume</groupId>
    <artifactId>flume-ng-core</artifactId>
    <version>1.9.0</version>
</dependency>
package com.simwor.bigdata.flume;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.util.List;

public class MyInterceptor implements Interceptor {
    @Override public void initialize() { }

    @Override public Event intercept(Event event) {
        byte[] body = event.getBody();

        if(body[0] >= '0' && body[0] <= '9')
            event.getHeaders().put("type", "number");
        else
            event.getHeaders().put("type", "letter");

        return event;
    }

    @Override public List<Event> intercept(List<Event> events) {
        for(Event event : events)
            intercept(event);

        return events;
    }

    @Override public void close() { }

    public static class MyBuilder implements Interceptor.Builder {
        @Override public Interceptor build() { return new MyInterceptor(); }
        @Override public void configure(Context context) { }
    }
}

maven clean package 后上传 Jar 包至 flume/lib/

[omm@bigdata01 lib]$ pwd
/opt/module/flume/lib
[omm@bigdata01 lib]$ ll | grep flume-1.0-SNAPSHOT
-rw-r--r-- 1 omm omm    2938 Mar 10  2021 flume-1.0-SNAPSHOT.jar
[omm@bigdata01 lib]$ 
[omm@bigdata01 job]$ vi myinterceptor.conf 
[omm@bigdata01 job]$ cat myinterceptor.conf 
a1.sources = r1
a1.channels = c1 c2
a1.sinks = k1 k2

a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata01
a1.sources.r1.port = 11111

a1.sources.r1.selector.type = multiplexing
a1.sources.r1.selector.header = type
a1.sources.r1.selector.mapping.letter = c1
a1.sources.r1.selector.mapping.number = c2

a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = com.simwor.bigdata.flume.MyInterceptor$MyBuilder

a1.channels.c1.type = memory
a1.channels.c2.type = memory

a1.sinks.k1.type = avro
a1.sinks.k1.hostname = bigdata02
a1.sinks.k1.port = 22222
a1.sinks.k2.type = avro
a1.sinks.k2.hostname = bigdata03
a1.sinks.k2.port = 33333

a1.sources.r1.channels = c1 c2
a1.sinks.k1.channel = c1
a1.sinks.k2.channel = c2
[omm@bigdata01 job]$ flume-ng agent -n a1 -c ../conf/ -f myinterceptor.conf -Dflume.root.logger=INFO,console
[omm@bigdata03 job]$ vi myinterceptor.conf 
[omm@bigdata03 job]$ cat myinterceptor.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata03
a1.sources.r1.port = 33333

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata03 job]$ flume-ng agent -n a1 -c ../conf/ -f myinterceptor.conf -Dflume.root.logger=INFO,console
[omm@bigdata02 job]$ vi myinterceptor.conf 
[omm@bigdata02 job]$ cat myinterceptor.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = avro
a1.sources.r1.bind = bigdata02
a1.sources.r1.port = 22222

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata02 job]$ flume-ng agent -n a1 -c ../conf/ -f myinterceptor.conf -Dflume.root.logger=INFO,console

在这里插入图片描述

3.2 自定义Source

需求:使用flume接收数据,并给每条数据添加前缀,输出到控制台,前缀可从flume配置文件中配置。

  • 介绍
  1. Source是负责接收数据到Flume Agent的组件。
  2. Source组件可以处理各种类型、各种格式的日志数据,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy。
  3. 官方提供的source类型已经很多,但是有时候并不能满足实际开发当中的需求,此时我们就需要根据实际需求自定义某些source。
  • 官方接口

https://flume.apache.org/FlumeDeveloperGuide.html#source,MySource需要继承AbstractSource类并实现Configurable和PollableSource接口。

  1. getBackOffSleepIncrement()//暂不用
  2. getMaxBackOffSleepInterval()//暂不用
  3. configure(Context context)//初始化context(读取配置文件内容)
  4. process()//获取数据封装成event并写入channel,这个方法将被循环调用。
package com.simwor.bigdata.flume;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.EventDeliveryException;
import org.apache.flume.PollableSource;
import org.apache.flume.channel.ChannelProcessor;
import org.apache.flume.conf.Configurable;
import org.apache.flume.event.SimpleEvent;
import org.apache.flume.source.AbstractSource;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义source
 * 需求 :使用flume接收数据,并给每条数据添加前缀,输出到控制台。前缀可从flume配置文件中配置。
 */
public class MySource extends AbstractSource implements Configurable, PollableSource {

    private String prefix;
    /**
     * 核心方法 - 获取数据封装成event,将创建的event放入到channel中。该方法会被循环调用
     * @return
     * @throws EventDeliveryException
     *
     * Status : 1.是一个枚举类  2.使用status的值来表示向ChannelProcessor中添加的数据是否成功
     *    READY : 添加event成功
     *    BACKOFF : 添加event失败
     */
    @Override
    public Status process() throws EventDeliveryException {
        Status status = Status.READY;

        //1.创建Event
        List<Event> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            //创建event的对象
            SimpleEvent event = new SimpleEvent();
            //给event中设置数据 + 前缀
            event.setBody((prefix + "hello" + i).getBytes());
            //将event放入到list中
            list.add(event);
        }
        //2.将数据放入到channel中(ChannelProccessor)
        try {

            //获取channelProcessor
            ChannelProcessor channelProcessor = getChannelProcessor();
            //将数据放入到channelProcessor
            channelProcessor.processEventBatch(list);
        }catch (Exception e){
            status = Status.BACKOFF;
        }
        return status;
    }

    //获取上下文,可以读取配置文件中的内容
    @Override
    public void configure(Context context) {
        //获取配置文件中的指定属性的内容,如果没有配置那么默认值为test
        prefix = context.getString("prefix","test=");
    }

    //当source没数据可封装时,会让source所在的线程休息一会
    @Override public long getBackOffSleepIncrement() { return 2000L;  }

    //当source没数据可封装时,会让source所在的线程休息的最大时间
    @Override public long getMaxBackOffSleepInterval() { return 5000L; }

}

maven clean package 后上传 Jar 包至 flume/lib/

[omm@bigdata01 lib]$ pwd
/opt/module/flume/lib
[omm@bigdata01 lib]$ ll | grep flume-1.0-SNAPSHOT
-rw-r--r-- 1 omm omm    2938 Mar 10  2021 flume-1.0-SNAPSHOT.jar
[omm@bigdata01 lib]$ 
[omm@bigdata01 job]$ cat mysource.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = com.simwor.bigdata.flume.MySource
a1.sources.r1.prefix = rayslee+

a1.channels.c1.type = memory

a1.sinks.k1.type = logger

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata01 job]$ 

在这里插入图片描述

3.3 自定义 Sink

需求:使用flume接收数据,并在Sink端给每条数据添加前缀和后缀,输出到控制台。前后缀可在flume任务配置文件中配置。

  • 介绍
  1. Sink不断地轮询Channel中的事件且批量地移除它们,并将这些事件批量写入到存储或索引系统、或者被发送到另一个Flume Agent。
  2. Sink是完全事务性的。在从Channel批量删除数据之前,每个Sink用Channel启动一个事务。批量事件一旦成功写出到存储系统或下一个Flume Agent,Sink就利用Channel提交事务。事务一旦被提交,该Channel从自己的内部缓冲区删除事件。
  3. Sink组件目的地包括hdfs、logger、avro、thrift、ipc、file、null、HBase、solr、自定义。官方提供的Sink类型已经很多,但是有时候并不能满足实际开发当中的需求,此时我们就需要根据实际需求自定义某些Sink。
  • 官方接口:

https://flume.apache.org/FlumeDeveloperGuide.html#sink,MySink需要继承AbstractSink类并实现Configurable接口。

  1. configure(Context context)//初始化context(读取配置文件内容)
  2. process()//从Channel读取获取数据(event),这个方法将被循环调用。
package com.simwor.bigdata.flume;

import org.apache.flume.*;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MySink extends AbstractSink implements Configurable {

    //读取到的配置文件中suffix的内容
    private String suffix;
    //获取Logger对象,可以将数据以日志的方式输出
    Logger logger = LoggerFactory.getLogger(MySink.class);

    /**
     * 核心方法,用来处理sink逻辑(将channel中的内容写出去) 被循环调用
     * @return
     * @throws EventDeliveryException
     */
    @Override
    public Status process() throws EventDeliveryException {
        Status status = Status.READY; //表示成功输入一个或多个event
        //1.获取Channel
        Channel channel = getChannel();
        //2.从Channel中获取事务
        Transaction transaction = channel.getTransaction();
        try {
            Event event = null;
            //2.1开启事务
            transaction.begin();
            //可能获取数据时没有获取到,所以下面的方法是用来保证获取到数据后再向logger中输出
            while (true) {
                //3.获取数据
                event = channel.take();
                if (event != null) {
                    break;
                }
                //else{
                //休息一下再去取数据
                //}
            }

            //4.将数据写出(mysql存,写本地磁盘上都可以)
            logger.info(new String(event.getBody()) +  suffix);
            //5.提交事务
            transaction.commit();
        }catch (Exception e){
            status = Status.BACKOFF; //获取数据失败
            //事务回滚
            transaction.rollback();
        }finally {
            //将事务关闭
            transaction.close();
        }
        return status;
    }

    /**
     * 获取上下文信息,用来读取配置文件中的内容
     * @param context
     */
    @Override
    public void configure(Context context) {
        suffix = context.getString("suffix","test");
    }
}

maven clean package 后上传 Jar 包至 flume/lib/

[omm@bigdata01 lib]$ pwd
/opt/module/flume/lib
[omm@bigdata01 lib]$ ll | grep flume-1.0-SNAPSHOT
-rw-r--r-- 1 omm omm    2938 Mar 10  2021 flume-1.0-SNAPSHOT.jar
[omm@bigdata01 lib]$ 
[omm@bigdata01 job]$ cat mysink.conf 
a1.sources = r1
a1.channels = c1
a1.sinks = k1

a1.sources.r1.type = netcat
a1.sources.r1.bind = bigdata01
a1.sources.r1.port = 11111

a1.channels.c1.type = memory

a1.sinks.k1.type = com.simwor.bigdata.flume.MySink
a1.sinks.k1.suffix = +rayslee

a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
[omm@bigdata01 job]$ 

在这里插入图片描述

四、知识点

  • Flume的Source,Sink,Channel的作用?
  1. Source组件是专门用来收集数据的,可以处理各种类型、各种格式的日志数据,包括avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy
  2. Channel组件对采集到的数据进行缓存,可以存放在Memory或File中。
  3. Sink组件是用于把数据发送到目的地的组件,目的地包括Hdfs、Logger、avro、thrift、ipc、file、Hbase、solr、自定义。
  • Flume的Channel Selectors

在这里插入图片描述

  • Source 参数调优
  1. 增加Source个(使用Tair Dir Source时可增加FileGroups个数)可以增大Source的读取数据的能力。
  2. 例如:当某一个目录产生的文件过多时需要将这个文件目录拆分成多个文件目录,同时配置好多个Source 以保证Source有足够的能力获取到新产生的数据。
  3. batchSize参数决定Source一次批量运输到Channel的event条数,适当调大这个参数可以提高Source搬运Event到Channel时的性能。
  • Channel 参数调优
  1. type 选择memory时Channel的性能最好,但是如果Flume进程意外挂掉可能会丢失数据。type选择file时Channel的容错性更好,但是性能上会比memory channel差。
  2. 使用file Channel时dataDirs配置多个不同盘下的目录可以提高性能。
  3. Capacity 参数决定Channel可容纳最大的event条数。
  4. transactionCapacity 参数决定每次Source往channel里面写的最大event条数和每次Sink从channel里面读的最大event条数。
  5. transactionCapacity需要大于Source和Sink的batchSize参数。
  • Sink 参数调优
  1. 增加Sink的个数可以增加Sink消费event的能力。
  2. Sink也不是越多越好够用就行,过多的Sink会占用系统资源,造成系统资源不必要的浪费。
  3. batchSize参数决定Sink一次批量从Channel读取的event条数,适当调大这个参数可以提高Sink从Channel搬出event的性能。
  • Flume的事务机制
  1. Flume的事务机制(类似数据库的事务机制):Flume使用两个独立的事务分别负责从Soucrce到Channel,以及从Channel到Sink的事件传递。
  2. 比如spooling directory source 为文件的每一行创建一个事件,一旦事务中所有的事件全部传递到Channel且提交成功,那么Soucrce就将该文件标记为完成。
  3. 同理,事务以类似的方式处理从Channel到Sink的传递过程,如果因为某种原因使得事件无法记录,那么事务将会回滚。且所有的事件都会保持到Channel中,等待重新传递。
  • Flume采集数据会丢失吗?
  1. 根据Flume的架构原理,Flume是不可能丢失数据的,其内部有完善的事务机制,Source到Channel是事务性的,Channel到Sink是事务性的,因此这两个环节不会出现数据的丢失,唯一可能丢失数据的情况是Channel采用memoryChannel,agent宕机导致数据丢失,或者Channel存储数据已满,导致Source不再写入,未写入的数据丢失。
  2. Flume不会丢失数据,但是有可能造成数据的重复,例如数据已经成功由Sink发出,但是没有接收到响应,Sink会再次发送数据,此时可能会导致数据的重复。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark Structured Streaming是一种基于Spark SQL引擎的流处理框架,它可以实现实时数据处理和分析。在使用Spark Structured Streaming进行大数据处理时,需要注意以下几点最佳实践: 1. 使用高可用性的集群:在使用Spark Structured Streaming时,需要保证集群的高可用性,以确保数据处理的稳定性和可靠性。 2. 选择合适的数据源:Spark Structured Streaming支持多种数据源,包括Kafka、Flume、HDFS等,需要根据实际情况选择合适的数据源。 3. 设计合理的数据处理流程:在设计数据处理流程时,需要考虑数据的实时性、处理效率和数据质量等因素,以确保数据处理的准确性和高效性。 4. 优化性能:在使用Spark Structured Streaming进行大数据处理时,需要优化性能,包括调整资源分配、调整并行度、使用缓存等方法,以提高数据处理的效率和速度。 5. 监控和调试:在使用Spark Structured Streaming进行大数据处理时,需要进行监控和调试,及时发现和解决问题,以确保数据处理的稳定性和可靠性。 ### 回答2: Spark Structured Streaming是一种用于实时流式数据处理的大数据最佳实践。它是Apache Spark的一部分,提供了一种简单而强大的方式来处理连续的数据流。 Spark Structured Streaming的实现原理基于Spark的弹性分布式数据集(RDD)模型,它将数据流视为一系列连续的批处理作业。这使得开发者能够使用Spark的强大功能进行实时数据分析和处理。 Spark Structured Streaming的关键特性包括: 1. 高级API:Structured Streaming提供了一种高级API,可以轻松地处理数据流。开发者只需编写一次数据处理逻辑,然后Spark会自动将其应用于连续的数据流。 2. 实时处理:Structured Streaming能够以低延迟处理数据流,提供近实时的结果。 3. 容错性:Structured Streaming具有Spark的容错机制,可以自动处理故障并继续处理数据流,确保数据不丢失。 4. 高吞吐量:Structured Streaming能够处理大规模的数据流,具有较高的吞吐量和扩展性。 5. 与其他Spark组件的集成:Structured Streaming可以与其他Spark组件(如Spark SQL和MLlib)无缝集成,从而可以方便地进行数据分析和机器学习任务。 在实践,可以使用Spark Structured Streaming来解决许多实时数据处理的问题。例如,可以使用它进行实时日志分析、实时监测和预测、实时推荐和广告投放等。 总而言之,Spark Structured Streaming是一种强大且灵活的实时数据处理解决方案,适用于大规模的数据流处理场景。它提供了简单的API和高性能的处理能力,为开发者提供了处理实时数据流的最佳实践。 ### 回答3: 大数据最佳实践,Spark的Structuring是一种优秀的实时处理框架,它针对流数据进行高效的处理和分析。StructStreaming提供了一种简单、易于使用的API来处理结构化数据流,并支持强大的时间窗口操作、累加器和支持容错的状态更新。 Spark StructStreaming的最佳实践包括以下几个方面: 1. 数据流处理:结构化流可以处理各种实时数据源,如Kafka、Flume等,并且能够处理高吞吐量和低延迟数据。在处理数据流时,可以使用规约、窗口操作等技术来实现实时的数据计算和聚合。 2. 内存优化:Spark StructStreaming可以将数据缓存到内存以提高性能,并使用解析器和列式存储来最大限度地减少内存占用和I/O开销。此外,通过调整内存分配和堆外内存配置,可以进一步优化性能。 3. 容错性和数据一致性:StructStreaming提供了容错性和一致性保证,可以在节点故障时自动恢复数据处理,并确保最终输出的一致性。 4. 结构化数据查询:Spark StructStreaming支持基于SQL的查询语言,可以使用SQL语句对流数据进行查询和分析。此外,还可以使用DataFrame和DataSet API进行更高级的数据操作和转换。 5. 流式机器学习:StructStreaming可以与Spark的机器学习库集成,实现基于流数据的实时机器学习模型训练和预测。通过结合流式数据和机器学习算法,可以实现实时的数据分析和预测。 总而言之,Spark StructStreamin的最佳实践是基于结构化数据流的实时处理和分析。它提供了简单易用的API和强大的功能,可以应用于各种大数据场景,并提供高性能、容错性和一致性保证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值