自己学习Flink时整理的一些笔记

自己学习Flink时整理的一些笔记,还不是很完整,后续慢慢增改,一起学习,有不同的看法或者意见可以私信或者评论

1 Flink概述

Flink是一个基于流式数据的有状态计算框架

Flink是一个分布式的大数据处理计算引擎/框架, 支持流式数据处理(当然也支持离线),支持有状态计算(当然也支持无状态),支持基于事件时间的延迟数据处理,支持复杂事件处理(CEP)....能够做到低延迟,高吞吐...

1.1 Flink的特点:

1)相对于Spark的流处理,Flink更优越

注意:

Spark的流处理:

SparkStreaming是用批处理的思想做流处理(微批处理),或多或少会有时间延迟!做不到毫秒级,一般也就秒级

StructuredStreaming可以做微批处理,也可以做连续处理(还不稳定,功能有很多限制)

Flink的流处理:

Flink是真正的流处理,可以做到基于事件的实时数据处理

2Flink支持多种灵活的时间窗口

3Flink支持复杂事件处理(CEP)

4)支持基于事件时间的延迟数据处理(StructuredStreaming也支持,但是不够强大)

6)支持StateCheckpoint(SparkStreaming也支持,但是不够强大)

......

1.2Flink原理

Flink的组件栈

 

1.2.1 Flink四大基石

 

1.2.2 Flink执行流程

Standalone版本

 

1.用户提交任务给JobClient

2.JobClient发送任务给JobManager

3.JobManager返回提交成功

4.JobManager将任务分发给TaskManager执行

5.TaskManager汇报任务的执行状态给JobManager

6.任务执行结束JobManager返回执行结果给JobClient

OnYarn版本

 

1.Client上传Flink任务的jar包和配置到HDFS

2.ClientYarn(ResourceManager)提交任务并申请资源

3.ResourceManager分配并启动ApplicationMaster并读取HDFS上的Flink任务配置信息

4.ApplicationMaster根据任务配置信息给Flink任务分配资源启动JobManagerTaskManager

5.JobManager将任务分发给TaskManager执行(TaskManager执行时需要去HDFS上读取任务jar)

1.2.3 Flink角色分工

 

FlinkClient

主要职责:(类似Driver)

接收用户的提交的程序代码,然后创建DataFlow模型(类似于DAG),DataFlow数据流提交给JobManager

JobManager

主要职责:(类似于Driver+Master)

负责整个Flink集群任务的调度和Flink内部资源的管理,包括调度计算任务task,管理Checkpoint....

TaskManager

主要职责:(类似于Worker/Executor)

负责具体的任务的执行

2 批处理DataSet

2.1 批处理-Data Sources

2.1.1基于集合

(1)使用env.fromElements()支持Tuple,自定义对象等复合形式。

(2)使用env.fromCollection()支持多种Collection的具体类型

(3)使用env.generateSequence()支持创建基于Sequence的DataSet

2.1.2 基于文件

(1)读取本地文件数据

(2)读取HDFS文件数据

(3)读取CSV文件数据

(4)读取压缩文件

2.2 批处理-Transformation

Transformation

Description

Map

在算子中得到一个元素并生成一个新元素data.map { x => x.toInt }

FlatMap

在算子中获取一个元素, 并生成任意个数的元素data.flatMap { str => str.split(" ") }

MapPartition

类似Map, 但是一次Map一整个并行分区data.mapPartition { in => in map { (_, 1) } }

Filter

如果算子返回true则包含进数据集, 如果不是则被过滤掉data.filter { _ > 100 }

Reduce

通过将两个元素合并为一个元素, 从而将一组元素合并为一个元素data.reduce { _ + _ }

ReduceGroup

将一组元素合并为一个或者多个元素data.reduceGroup { elements => elements.sum }

Aggregate

讲一组值聚合为一个值, 聚合函数可以看作是内置的Reduce函数data.aggregate(SUM, 0).aggregate(MIN, 2)data.sum(0).min(2)

Distinct

去重

Join

按照相同的Key合并两个数据集input1.join(input2).where(0).equalTo(1)同时也可以选择进行合并的时候的策略, 是分区还是广播, 是基于排序的算法还是基于哈希的算法input1.join(input2, JoinHint.BROADCAST_HASH_FIRST).where(0).equalTo(1)

OuterJoin

外连接, 包括左外, 右外, 完全外连接等left.leftOuterJoin(right).where(0).equalTo(1) { (left, right) => ... }

CoGroup

二维变量的Reduce运算, 对每个输入数据集中的字段进行分组, 然后join这些组input1.coGroup(input2).where(0).equalTo(1)

Cross

笛卡尔积input1.cross(input2)

Union

并集input1.union(input2)

Rebalance

分区重新平衡, 以消除数据倾斜input.rebalance()

Hash-Partition

按照Hash分区input.partitionByHash(0)

Range-Partition

按照Range分区input.partitionByRange(0)

CustomParititioning

自定义分区input.partitionCustom(partitioner: Partitioner[K], key)

First-n

返回数据集中的前n个元素input.first(3)

partitionByHash

按照指定的key进行hash分区

sortPartition

指定字段对分区中的数据进行排序

mapmapPartition

Spark一样

map对每一个元素操作

mapPartition对每一个分区操作
flatMap

用法和Spark中的一模一样,有一个新的用法 DataSet中的每一个元素转换为另一个集合并压平为多个元素 DataSet中的每一个元素转换为0~n个元素

Filter

过滤

groupBy+reducegroupBy+sum

groupBy+reduce:分组+聚合

groupBy+sum:分组+聚合

groupBy+reduceGroup:

reduce:会将各个分区的数据拉取到主节点再聚合计算

reduceGroup:会将各个分区的数据先进行预聚合,再将结果发送给主节点

groupBy+reduceGroup = Spark中的reduceByKey

Aggregate

Aggregate是聚合的底层API

Distinct

去重

Join:

内连接

左外连接,左边的Dataset中的每一个元素,去连接右边的元素, 左边的全部保留,右边的满足条件的保留

fullOuterJoin

全外连接,左右两边的元素,全部连接

Rebalance

重平衡--按照轮询Round Robin进行平衡

kafka中如果消息没有key,那么这个消息发给各个分区就是使用轮询;如果消息有key默认就使用hash

类似于Spark中通过repartition解决数据倾斜

Flink中可以使用rebalance来解决数据倾斜

分区

partitionByHash按照hash值进行分区 partitionByRange按照数值范围进行分区 sortPartition对分区进行排序

minBymin

min:可以求最小,但不能保证其他列正确

minBy:可以求最小,也能够保证其他列正确

maxBymax类似

2.3 批处理-Data Sinks

2.3.1 基于集合

基于本地集合的sink(Collection-based-sink)

可以sink到标准输出,error输出,collect()到本地集合

2.3.2 基于文件

基于文件的sink(File-based-sink)

可以sink到本地文件,hdfs文件(支持多种文件的存储格式,包括text文件,CSV文件等)

writeAsText():TextOuputFormat - 将元素作为字符串写入行。字符串是通过调用每个元素的toString()方法获得的。

3 流处理DataStream

3.1 流处理-DataSource

3.1.1 基于集合(参考批处理)

3.1.2 基于文件的(参考批处理)

3.1.3 基于Socket

3.1.4自定义source

3.2 流处理-Transformation

Transformation

Description

Map
DataStream→DataStream

Takes one element and produces one element. A map function that doubles the values of the input stream:

dataStream.map { x => x * 2 }

FlatMap
DataStream→DataStream

采用一个数据元并生成零个,一个或多个数据元。将句子分割为单词的flatmap函数:

dataStream.flatMap { str => str.split(" ") }

Filter
DataStream→DataStream

计算每个数据元的布尔函数,并保存函数返回true的数据元。过滤掉零值的过滤器:

dataStream.filter { _ != 0 } 

KeyBy
DataStream→KeyedStream

逻辑上将流分区为不相交的分区。具有相同Keys的所有记录都分配给同一分区。在内部,keyBy()是使用散列分区实现的。指定键有不同的方法。

此转换返回KeyedStream,其中包括使用Keys化状态所需的KeyedStream

dataStream.keyBy("someKey") // Key by field "someKey"
dataStream.keyBy(0) // Key by the first element of a Tuple

Reduce
KeyedStream→DataStream

Keys化数据流上的滚动”Reduce。将当前数据元与最后一个Reduce的值组合并发出新值。 

reduce函数,用于创建部分和的流:

keyedStream.reduce { _ + _ }  

Fold
KeyedStream→DataStream

具有初始值的被Keys化数据流上的滚动折叠。将当前数据元与最后折叠的值组合并发出新值。 

折叠函数,当应用于序列(1,2,3,4,5)时,发出序列“start-1”“start-1-2”“start-1-2-3”,. ..

val result: DataStream[String] =  keyedStream.fold("start")((str, i) => { str + "-" + i })  

Aggregations
KeyedStream→DataStream

在被Keys化数据流上滚动聚合。minminBy之间的差异是min返回最小值,而minBy返回该字段中具有最小值的数据元(maxmaxBy相同)

keyedStream.sum(0);
keyedStream.sum("key");
keyedStream.min(0);
keyedStream.min("key");
keyedStream.max(0);
keyedStream.max("key");
keyedStream.minBy(0);
keyedStream.minBy("key");
keyedStream.maxBy(0);
keyedStream.maxBy("key");    

Window
KeyedStream→WindowedStream

可以在已经分区的KeyedStream上定义WindowsWindows根据某些特征(例如,在最后5秒内到达的数据)对每个Keys中的数据进行分组。有关窗口的完整说明,请参见windows

dataStream.keyBy(0).window(TumblingEventTimeWindows.of(Time.seconds(5))); // Last 5 seconds of data   

WindowAll
DataStream→AllWindowedStream

Windows可以在常规DataStream上定义。Windows根据某些特征(例如,在最后5秒内到达的数据)对所有流事件进行分组。有关窗口的完整说明,请参见windows

警告:在许多情况下,这是非并行转换。所有记录将收集在windowAll 算子的一个任务中。

dataStream.windowAll(TumblingEventTimeWindows.of(Time.seconds(5))); // Last 5 seconds of data  

Window Apply
WindowedStream→DataStream 
AllWindowedStream→DataStream

将一般函数应用于整个窗口。下面是一个手动求和窗口数据元的函数。

注意:如果您正在使用windowAll转换,则需要使用AllWindowFunction

windowedStream.apply { WindowFunction }// applying an AllWindowFunction on non-keyed window stream
allWindowedStream.apply { AllWindowFunction }

Window Reduce
WindowedStream→DataStream

将函数缩减函数应用于窗口并返回缩小的值。

windowedStream.reduce { _ + _ }

Window Fold
WindowedStream→DataStream

将函数折叠函数应用于窗口并返回折叠值。示例函数应用于序列(1,2,3,4,5)时,将序列折叠为字符串“start-1-2-3-4-5”

val result: DataStream[String] = windowedStream.fold("start", (str, i) => { str + "-" + i }) 

Windows上的聚合
WindowedStream→DataStream

聚合窗口的内容。minminBy之间的差异是min返回最小值,而minBy返回该字段中具有最小值的数据元(maxmaxBy相同)

windowedStream.sum(0);windowedStream.sum("key");windowedStream.min(0);windowedStream.min("key");windowedStream.max(0);windowedStream.max("key");windowedStream.minBy(0);windowedStream.minBy("key");windowedStream.maxBy(0);windowedStream.maxBy("key");    

Union
DataStream *→DataStream

两个或多个数据流的联合,创建包含来自所有流的所有数据元的新流。注意:如果将数据流与自身联合,则会在结果流中获取两次数据元。

dataStream.union(otherStream1, otherStream2, ...);    

Window Join
DataStreamDataStream→DataStream

在给定Keys和公共窗口上连接两个数据流。

dataStream.join(otherStream)
    .where(<key selector>).equalTo(<key selector>)
    .window(TumblingEventTimeWindows.of(Time.seconds(3)))
    .apply (new JoinFunction () {...});    

Interval Join
KeyedStreamKeyedStream→DataStream

在给定的时间间隔内使用公共Keys关联两个被Key化的数据流的两个数据元e1e2,以便e1.timestamp + lowerBound <= e2.timestamp <= e1.timestamp + upperBound

// this will join the two streams so that// key1 == key2 && leftTs - 2 < rightTs < leftTs + 2keyedStream.intervalJoin(otherKeyedStream)
    .between(Time.milliseconds(-2), Time.milliseconds(2)) // lower and upper bound
    .upperBoundExclusive(true) // optional
    .lowerBoundExclusive(true) // optional
    .process(new IntervalJoinFunction() {...});    

Window CoGroup
DataStreamDataStream→DataStream

在给定Keys和公共窗口上对两个数据流进行Cogroup

dataStream.coGroup(otherStream)
    .where(0).equalTo(1)
    .window(TumblingEventTimeWindows.of(Time.seconds(3)))
    .apply (new CoGroupFunction () {...});    

Connect
DataStreamDataStream→ConnectedStreams

连接两个保存其类型的数据流。连接允许两个流之间的共享状态。

DataStream<Integer> someStream = //...DataStream<String> otherStream = //...ConnectedStreams<Integer, String> connectedStreams = someStream.connect(otherStream);    

CoMapCoFlatMap
ConnectedStreams→DataStream

类似于连接数据流上的mapflatMap

connectedStreams.map(
    (_ : Int) => true,
    (_ : String) => false)connectedStreams.flatMap(
    (_ : Int) => true,
    (_ : String) => false)

Split
DataStream→SplitStream

根据某些标准将流拆分为两个或更多个流。

val split = someDataStream.split(
  (num: Int) =>
    (num % 2) match {
      case 0 => List("even")
      case 1 => List("odd")
    })               

Select
SplitStream→DataStream

从拆分流中选择一个或多个流。

SplitStream<Integer> split;DataStream<Integer> even = split.select("even");DataStream<Integer> odd = split.select("odd");DataStream<Integer> all = split.select("even","odd");               

Iterate
DataStream→IterativeStream→DataStream

通过将一个 算子的输出重定向到某个先前的 算子,在流中创建反馈循环。这对于定义不断更新模型的算法特别有用。以下代码以流开头并连续应用迭代体。大于0的数据元将被发送回反馈通道,其余数据元将向下游转发。有关完整说明,请参阅迭代

initialStream.iterate {
  iteration => {
    val iterationBody = iteration.map {/*do something*/}
    (iterationBody.filter(_ > 0), iterationBody.filter(_ <= 0))
  }}           

Extract Timestamps
DataStream→DataStream

从记录中提取时间戳,以便使用使用事件时间语义的窗口。查看活动时间

stream.assignTimestamps (new TimeStampExtractor() {...});                

3.3 DataSink

3.3.1 基于集合(参考批处理)

3.3.2 基于文件(参考批处理)

3.3.3 自定义Sink-MySQL

3.3.4 自定义Sink-Kafka

4 Flink的Window操作

1.Flink支持两种划分窗口的方式(time和count)

      如果根据时间划分窗口,那么它就是一个time-window,比如每1分钟统计一次或每10分钟统计一次最近xxx的数据

      如果根据数据划分窗口,那么它就是一个count-window,比如每5个数据统计一次或每50个数据统计一次

2.Flink支持窗口的两个重要属性(窗口长度size和滑动间隔interval)

    如果size=interval,那么就会形成tumbling-window(无重叠数据)--滑动的特例--滚动窗口

    如果size>interval,那么就会形成sliding-window(有重叠数据)--正常的滑动窗口

    如果size<interval,那么这种窗口将会丢失数据。比如每5秒钟,统计过去3秒的通过路口汽车的数据,将会漏掉2秒钟的数据。

3.通过组合可以得出四种基本窗口

    time-tumbling-window 无重叠数据的时间窗口,设置方式举例:timeWindow(Time.seconds(5))---基于时间的滚动窗口

    time-sliding-window  有重叠数据的时间窗口,设置方式举例:timeWindow(Time.seconds(10), Time.seconds(5))---基于时间的滑动窗口

    count-tumbling-window无重叠数据的数量窗口,设置方式举例:countWindow(5)---基于数量的滚动窗口

count-sliding-window 有重叠数据的数量窗口,设置方式举例:countWindow(10,5)---基于数量的滑动窗口

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值