Data Sources

源是程序读取输入数据的位置。可以使用 StreamExecutionEnvironment.addSource(sourceFunction) 将源添加到程序。Flink 有许多预先实现的源函数,也可以通过实现 SourceFunction 方法自定义非并行源 ,或通过实现 ParallelSourceFunction 或扩展 RichParallelSourceFunction 自定义并行源。

有几个预定义的流数据源可从 StreamExecutionEnvironment 访问:

基于文件:

  • readTextFile(path) 逐行读取文本文件(文件符合 TextInputFormat 格式),并作为字符串返回每一行。
  • readFile(fileInputFormat, path) 按指定的文件输入格式(fileInputFormat)读取指定路径的文件。

  • readFile(fileInputFormat, path, watchType, interval, pathFilter) 前两个方法的内部调用方法。根据给定文件格式(fileInputFormat)读取指定路径的文件。根据 watchType,定期监听路径下的新数据(FileProcessingMode.PROCESS_CONTINUOUSLY),或者处理当前在路径中的数据并退出(FileProcessingMode.PROCESS_ONCE)。使用 pathFilter,可以进一步排除正在处理的文件。

基于Socket:

  • socketTextStream 从 Socket 读取,元素可以用分隔符分隔。

基于集合:

  • fromCollection(Seq) 用 Java.util.Collection 对象创建数据流。集合中的所有元素必须属于同一类型。

  • fromCollection(Iterator) 用迭代器创建数据流。指定迭代器返回的元素的数据类型。

  • fromElements(elements: _*) 从给定的对象序列创建数据流。所有对象必须属于同一类型。

  • fromParallelCollection(SplittableIterator) 并行地从迭代器创建数据流。指定迭代器返回的元素的数据类型。

  • generateSequence(from, to) 并行生成给定间隔的数字序列。

自定义:

  • addSource 附加新的源函数。例如,要从 Apache Kafka 中读取,可以使用 addSource(new FlinkKafkaConsumer08<>(...))。请详细查看 连接器

DataStream Transformation

转换函数

Map
DataStream -> DataStream,一个数据元生成一个新的数据元。
将输入流的元素翻倍:
dataStream.map { x => x * 2 }

FlatMap
DataStream -> DataStream,一个数据元生成多个数据元(可以为0)。将句子分割为单词:
dataStream.flatMap { str => str.split(" ") }

Filter
DataStream -> DataStream,每个数据元执行布尔函数,只保存函数返回 true 的数据元。过滤掉零值的过滤器:
dataStream.filter { _ != 0 }

KeyBy
DataStream -> KeyedStream,将流划分为不相交的分区。具有相同 Keys 的所有记录在同一分区。指定 key 的取值:

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

Reduce
KeyedStream -> DataStream,KeyedStream 元素滚动执行 Reduce。将当前数据元与最新的一个 Reduce 值组合作为新值发送。创建 key 的值求和:

keyedStream.reduce { _ + _ }

Fold
KeyedStream -> DataStream,具有初始值的 Reduce。将当前数据元与最新的一个 Reduce 值组合作为新值发送。当应用于序列(1,2,3,4,5)时,发出序列"start-1","start-1-2","start-1-2-3", ...:

keyedStream.fold("start")((str, i) => { str + "-" + i })

Aggregations
KeyedStream -> DataStream,应用于 KeyedStream 上的滚动聚合。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,Windows 可以在已经分区的 KeyedStream 上定义。Windows 根据某些特征(例如,在最近5秒内到达的数据)对每个Keys中的数据进行分组。更多说明参考 Windows译版

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

WindowAll
DataStream -> AllWindowedStream,Windows 也可以在 DataStream 上定义。在许多情况下,这是非并行转换。所有记录将收集在 windowAll 算子的一个任务中。

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

Window Apply
WindowedStream -> DataStream 或 AllWindowedStream -> DataStream,将函数应用于整个窗口。一个对窗口数据求和:

windowedStream.apply { WindowFunction }

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

Window Reduce
WindowedStream -> DataStream,Reduce 函数应用于窗口并返回结果值。

windowedStream.reduce { _ + _ }

Window Fold
WindowedStream -> DataStream,Fold 函数应用于窗口并返回结果值。当函数应用于窗口的序列(1,2,3,4,5)时,发送出 "start-1-2-3-4-5":

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

Aggregations on windows
WindowedStream -> DataStream,聚合窗口的内容:

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
DataStream,DataStream -> DataStream,Join 连接两个流,指定 Key 和窗口。

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

Window CoGroup
DataStream,DataStream -> DataStream,CoGroup 连接两个流,指定 Key 和窗口。

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

CoGroup 与 Join 的区别:
CoGroup 会输出未匹配的数据,Join 只输出匹配的数据

Connect
DataStream,DataStream -> ConnectedStreams,连接两个有各自类型的数据流。允许两个流之间的状态共享。

someStream : DataStream[Int] = ...
otherStream : DataStream[String] = ... val connectedStreams = someStream.connect(otherStream)

可用于数据流关联配置流

CoMap, CoFlatMap
ConnectedStreams -> DataStream,作用域连接数据流(connected data stream)上的 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,从 SpliteStream 中选择一个流或多个流。

val even = split select "even"
val odd = split select "odd"
val all = split.select("even","odd")

Iterate
DataStream -> IterativeStream -> DataStream,将一个算子的输出重定向到某个先前的算子,在流中创建 feedback 循环。这对于定义不断更新模型的算法特别有用。以下代码以流开头并连续应用迭代体。大于0的数据元将被发送回 feedback,其余数据元将向下游转发。

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

Extract Timestamps
DataStream -> DataStream,从记录中提取时间戳,以便使用事件时间窗口。

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

Project
DataStream -> DataStream,作用于元组的转换,从元组中选择字段的子集。

DataStream<Tuple3<Integer, Double, String>> in = // [...]
DataStream<Tuple2<String, Integer>> out = in.project(2,0);

分区函数

Custom partitioning
DataStream -> DataStream,使用自定义的分区函数(Partitioner)为每个数据元选择目标分区和所在任务。

dataStream.partitionCustom(partitioner, "someKey");
dataStream.partitionCustom(partitioner, 0);

Random partitioning
DataStream -> DataStream,随机均匀分布分配数据元。

dataStream.shuffle();

Rebalancing (Round-robin partitioning)
DataStream -> DataStream,轮询为数据元分区,每个分区创建相等的负载。在存在数据偏斜时用于性能优化。

dataStream.rebalance()

Rescaling
DataStream -> DataStream,根据上下游的分区数量,轮询为数据元分区。

dataStream.rescale();

建议使用 rescale 替代 rebalance
例如,上游是5个并发,下游是10个并发。当使用 Rebalance 时,上游每个并发会轮询发给下游10个并发。当使用 Rescale 时,上游每个并发只需轮询发给下游2个并发,能提高网络效率。
当上游的数据比较均匀时,且上下游的并发数成比例时,可以使用 Rescale 替换 Rebalance。参数:enable.rescale.shuffling=true,默认关闭。

Broadcasting
DataStream -> DataStream,向每个分区广播数据元。

dataStream.broadcast()

Task chaining and resource groups

Chaining 两个后续转换意味着将它们定位在同一个线程中以获得更好的性能。Flink 默认会链接一些算子(例如,连续两个的 map 转换)。API可以对链接进行细粒度控制:

使用 StreamExecutionEnvironment.disableOperatorChaining() 可以禁用整个工作的算子链接。对于更细粒度的控制,可以使用以下函数。(这些函数只能在 DataStream 转换后立即使用。例如,可以使用 someStream.map(...).startNewChain(),但不能使用 someStream.startNewChain()

Resource group 是 Flink 中的一个 slot。如果需要,可以在单独的 slot 中手动隔离算子。

Start new chain
从这个算子开始,开始一个新的链。两个 map 将被链接,filter 将不会在链接当中。

someStream.filter(...).map(...).startNewChain().map(...)

Disable chaining
不要链接 map 算子

someStream.map(...).disableChaining()

Set slot sharing group
设置算子操作的 slot sharing。将把具有相同 slot sharing 的算子操作放入同一个 slot,同时保证其他 slot 中没有 slot sharing 的算子操作。可用于隔离 slot。默认 slot sharing group 的名称为"default",可以通过调用 slotSharingGroup("groupName") 将算子操作显式放入此组中。

someStream.filter(...).slotSharingGroup("name")

Data Sinks

Data Sink 消费 DataStream 并转发到文件,套接字,外部系统或打印到页面。Flink 带有各种内置输出格式,封装在 DataStreams 上的算子操作后面:

  • writeAsText() / TextOutputFormat, 按字符串顺序写入文件。通过调用每个元素的 toString() 方法获得字符串。

  • writeAsCsv(...) / CsvOutputFormat,将元组写为逗号分隔的形式写入文件。行和字段分隔符是可配置的。每个字段的值来自对象的 toString() 方法。

  • print() / printToErr(),在标准输出/标准错误流上打印每个元素的 toString() 值。可以定义输出前缀,这有助于区分不同的打印调用。如果并行度大于1,输出也包含生成输出的任务的标识符。

  • writeUsingOutputFormat() / FileOutputFormat,自定义文件输出的方法和基类。支持自定义对象到字节的转换。

  • writeToSocket,将元素写入 Socket,使用 SerializationSchema 进行序列化。

  • addSink,调用自定义接收器函数。请详细查看 连接器

DataStream 的 write*() 方法主要用于调试目的。他们没有参与 Flink checkpoint,这意味着这些函数通常具有至少一次的语义。刷新到目标系统的数据取决于 OutputFormat 的实现,并非所有发送到 OutputFormat 的数据都会立即显示在目标系统中。此外,在失败的情况下,这些记录可能会丢失。

要将流可靠、准确地传送到文件系统,请使用 flink-connector-filesystem。通过 .addSink(...) 方法的自定义实现,可以实现在 checkpoint 中精确一次的语义。

Iterations

迭代流程序将函数嵌入到 IterativeStream。由于 DataStream 程序可能永远不会完成,因此没有最大迭代次数。相反,需要指定流的哪个部分反馈到迭代,哪个部分使用 split 或 filter 转发到下游。

下面是一个示例迭代,其中主体(重复的计算部分)是一个简单的 map 转换,反馈的元素由使用过滤器向下游转发的元素区分。

val iteratedStream = someDataStream.iterate(
iteration => {
val iterationBody = iteration.map(/* this is executed many times */)
(iterationBody.filter(/* one part of the stream */), iterationBody.filter(/* some other part of the stream */))
})

例如,从一系列整数中连续减去1直到它们达到零的程序:

val someIntegers: DataStream[Long] = env.generateSequence(0, 1000)

val iteratedStream = someIntegers.iterate(
iteration => {
val minusOne = iteration.map( v => v - 1)
val stillGreaterThanZero = minusOne.filter (_ > 0)
val lessThanZero = minusOne.filter(_ <= 0)
(stillGreaterThanZero, lessThanZero)
}
)

Reference:
https://ci.apache.org/projects/flink/flink-docs-release-1.6/dev/datastream_api.html

转载:https://www.jianshu.com/p/3e3d43e2bee0

Flink DataStream API的更多相关文章

  1. flink DataStream API使用及原理

    传统的大数据处理方式一般是批处理式的,也就是说,今天所收集的数据,我们明天再把今天收集到的数据算出来,以供大家使用,但是在很多情况下,数据的时效性对于业务的成败是非常关键的. Spark 和 Flin ...

  2. Flink DataStream API Programming Guide

    Example Program The following program is a complete, working example of streaming window word count ...

  3. Flink DataStream API 中的多面手——Process Function详解

    之前熟悉的流处理API中的转换算子是无法访问事件的时间戳信息和水位线信息的.例如:MapFunction 这样的map转换算子就无法访问时间戳或者当前事件的时间. 然而,在一些场景下,又需要访问这些信 ...

  4. Flink Program Guide (2) -- 综述 (DataStream API编程指导 -- For Java)

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  5. Flink中API使用详细范例--window

    Flink Window机制范例实录: 什么是Window?有哪些用途? 1.window又可以分为基于时间(Time-based)的window 2.基于数量(Count-based)的window ...

  6. Flink-v1.12官方网站翻译-P016-Flink DataStream API Programming Guide

    Flink DataStream API编程指南 Flink中的DataStream程序是对数据流实现转换的常规程序(如过滤.更新状态.定义窗口.聚合).数据流最初是由各种来源(如消息队列.套接字流. ...

  7. Flink Program Guide (10) -- Savepoints (DataStream API编程指导 -- For Java)

    Savepoint 本文翻译自文档Streaming Guide / Savepoints ------------------------------------------------------ ...

  8. Flink Program Guide (8) -- Working with State :Fault Tolerance(DataStream API编程指导 -- For Java)

    Working with State 本文翻译自Streaming Guide/ Fault Tolerance / Working with State ---------------------- ...

  9. Flink Program Guide (3) -- Event Time (DataStream API编程指导 -- For Java)

    Event Time 本文翻译自DataStream API Docs v1.2的Event Time ------------------------------------------------ ...

随机推荐

  1. client-go获取k8s集群内部连接,实现deployment的增删改查

    一开始写了一个client-java版本的,但是java放在k8s集群上跑需要装jvm而且java的包比较大,client-go版本更适合主机端,下面是整个实现 说明:k8s官方维护的客户端库只有go ...

  2. 使用python实现希尔、计数、基数排序

    希尔排序 希尔排序是一个叫希尔的数学家提出的一种优化版本的插入排序. 首先取一个整数d1=n//2,将元素分为d1个组,每组相邻元素之间的距离为d1,在各组内进行直接插入排序. 取第二个整数d2=d1 ...

  3. python学习笔记:sys、os模块

    os模块:负责程序与操作系统的交互,提供了访问操作系统底层的接口; sys模块:负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境. --os 常用方法-- ...

  4. UVA11134_Fabled Rooks

    大概题意: 在n*n的棋盘上面放n个车,能否使他们互相不攻击(即不能在同一行一列),并且第i个车必须落在第i的矩形范围(xl,yl, xr,yr)之内 xy互相并不干扰,所以就可以把这个二维问题压缩成 ...

  5. oracle查询不显示小数点前的0

    1.问题起源       oracle 数据库字段值为小于1的小数时,使用char类型处理,会丢失小数点前面的0       例如0.35就变成了.35 2.解决办法:用to_char函数格式化数字显 ...

  6. VS2008的使用

    文章转载自:http://www.cnblogs.com/aduck/archive/2011/11/11/2245460.html 1.如何在vc2008中显示行号 中文版: 菜单-工具-选项 在新 ...

  7. JavaScript 学习笔记(初学者)

    Java Script 基础 一. JS的简介     JavaScript是一种网页编程技术,经常用于创建动态交互网页     JavaScript是一种基于对象和事件驱动的解释性脚本语言,类似C语 ...

  8. 在同一个项目中灵活运用application/json 和application/x-www-form-urlencoded 两种传输格式(配合axios,同时配置loading)

    'use strict' import axios from 'axios' // import qs from 'qs' import { Notification} from 'element-u ...

  9. Excel_PoweQuery——条件计数、条件求和

    岁月不居,时节如流. 时光荏苒,岁月如梭. 前面两段充分体现了博主深厚的文学素养,别和博主争,博主说啥就是啥. 其实,对于大量数据的处理,这几年微软Office做的不单单是2007的时候把Excel的 ...

  10. 搜索solr

    这是我第一次写博客,没有系统性.专业性,东西很杂,也不知道自己在写些什么. SOA分布式架构,所以,使用solr,搜索层的服务层需要搭建起来.搜索系统的表现层搭建 ,打包方式是war包 域名改变代表系 ...