Flink中提供了4种不同层次的API,如图4.1所示,每种API在简洁和易用之间有自己的权衡,适用于不同的场景。目前其中的3种API用得比较多,下面自下向上介绍这4种API。
•低级API:提供了对时间和状态的细粒度控制,简洁性和易用性较差,主要应用在对一些复杂事件的处理逻辑上。
•核心API:主要提供了针对流数据和离线数据的处理,对低级API进行了一些封装,提供了filter、sum、max、min等高级函数,简单且易用,所以在工作中应用比较广泛。
•Table API:一般与DataSet或者DataStream紧密关联,首先通过一个DataSet或DataStream创建出一个Table;然后用类似于filter、join或者select关系型转化操作来转化为一个新的Table对象;最后将一个Table对象转回一个DataSet或DataStream。与SQL不同的是,Table API的查询不是一个指定的SQL字符串,而是调用指定的API方法。
•SQL:Flink的SQL集成是基于Apache Calcite的,Apache Calcite实现了标准的SQL,使用起来比其他API更加灵活,因为可以直接使用SQL语句。Table API和SQL可以很容易地结合在一块使用,它们都返回Table对象。
4.2 Flink DataStream的常用API
DataStream API主要分为3块:DataSource、Transformation、Sink。
•DataSource是程序的数据源输入,可以通过StreamExecutionEnvironment.addSource(sourceFunction)为程序添加一个数据源。•Transformation是具体的操作,它对一个或多个输入数据源进行计算处理,比如Map、FlatMap和Filter等操作。
•Sink是程序的输出,它可以把Transformation处理之后的数据输出到指定的存储介质中。
4.2.1 DataSource
Flink针对DataStream提供了大量的已经实现的DataSource(数据源)接口,比如下面4种。
1.基于文件
读取文本文件,文件遵循TextInputFormat逐行读取规则并返回。2.基于Socket
从Socket中读取数据,元素可以通过一个分隔符分开。3.基于集合
通过Java的Collection集合创建一个数据流,集合中的所有元素必须是相同类型的。
4.自定义输入addSource可以实现读取第三方数据源的数据。Flink也提供了一批内置的Connector(连接器)。连接器会提供对应的Source支持,如表4.1所示。
表4.1 Flink内置的连接器信息
Flink通过Apache Bahir组件提供了对这些连接器的支持,如表4.2所示。
表4.2 Flink通过Apache Bahir组件支持的连接器信息
注意:Flink提供的这些数据源接口的容错性保证如表4.3所示。
表4.3 DataSource提供的容错情况
当然也可以自定义数据源,有两种方式实现。
•通过实现SourceFunction接口来自定义无并行度(也就是并行度只能为1)的数 据源。
•通过实现ParallelSourceFunction 接口或者继承RichParallelSourceFunction 来自定义有并行度的数据源。
需求:实现并行度只能为1的自定义DataSource以及SourceFunction接口。
分析:模拟产生从1开始的递增数字,每次递增加1。Java代码实现如下。
4.2.2 Transformation'''''
Flink针对DataStream提供了大量的已经实现的算子。
•Map:输入一个元素,然后返回一个元素,中间可以进行清洗转换等操作。
•FlatMap:输入一个元素,可以返回零个、一个或者多个元素。
•Filter:过滤函数,对传入的数据进行判断,符合条件的数据会被留下。KeyBy:根据指定的Key进行分组,Key相同的数据会进入同一个分区。KeyBy的两种典型用法如下。DataStream.keyBy("someKey") 指定对象中的someKey段作为分组Key。DataStream.keyBy(0) 指定Tuple中的第一个元素作为分组Key。
•Reduce:对数据进行聚合操作,结合当前元素和上一次Reduce返回的值进行聚合操作,然后返回一个新的值。
•Aggregations:sum()、min()、max()等。
•Union:合并多个流,新的流会包含所有流中的数据,但是Union有一个限制,就是所有合并的流类型必须是一致的。
•Connect:和Union类似,但是只能连接两个流,两个流的数据类型可以不同,会对两个流中的数据应用不同的处理方法。•coMap和coFlatMap:在ConnectedStream中需要使用这种函数,类似于Map和flatMap。
•Split:根据规则把一个数据流切分为多个流。
•Select:和Split配合使用,选择切分后的流。另外,Flink针对DataStream提供了一些数据分区规则,具体如下。
•Random partitioning:随机分区。
•Rebalancing:对数据集进行再平衡、重分区和消除数据倾斜。
•Rescaling:重新调节。
如果上游操作有2个并发,而下游操作有4个并发,那么上游的1个并发结果分配给了下游的2个并发操作,另外的1个并发结果则分配给了下游的另外2个并发操作。另一方面,下游有2个并发操作而上游有4个并发操作,那么上游的其中2个操作的结果分配给了下游的一个并发操作,而另外2个并发操作的结果则分配给了另外1个并发操作。
Rescaling与Rebalancing的区别为Rebalancing会产生全量重分区,而Rescaling不会。
4.2.3 Sink
Flink针对DataStream提供了大量的已经实现的数据目的地(Sink),具体如下所示。
•writeAsText():将元素以字符串形式逐行写入,这些字符串通过调用每个元素的toString()方法来获取。
•print() / printToErr():打印每个元素的toString()方法的值到标准输出或者标准错误输出流中。
•自定义输出:addSink可以实现把数据输出到第三方存储介质中。系统提供了一批内置的Connector,它们会提供对应的Sink支持,如表4.1所示。Flink通过Apache Bahir组件也提供了对这些Connector的支持,
如表4.2所示。注意:针对Flink提供的这些Sink组件,它们可以提供的容错性保证如表4.4所示。
当然你也可以自定义Sink,有两种实现方式。•实现SinkFunction接口。•继承RichSinkFunction类。