• Flink程序是实现分布式集合转换的常规程序。集合最初是从源创建的。通过接收器(slink)返回结果,接收器可以将数据写到某个文件或stdout。Flink可以在各种环境(context)中运行,本地JVM或集群。

1.数据集和数据流

  • Flink用特殊的类DataSet and DataStream来表示程序中的数据。可以认为他们是可以包含重复数据的不可变数据集合。在DataSet中数据是有限的,而在DataStream中数据是无限的。
  • 这些集合不同于java里的集合,他们是不可变的,一旦被创造就不能改动,也不能简单的抽查里面的元素。
  • 最初的集合是通过在Flink程序里添加一个源被创造的,新的集合是使用API方法(如mapfilter)通过转换得到的。

2.剖析一个Flink程序

  • 每个程序包含相同的基本部分:
  1. 获得一个执行环境(execution environment).
  2. 加载/创建初始数据。
  3. 指定转换这些数据。
  4. 指定放置计算结果的位置。
  5. 触发程序执行。
  • StreamExecutionEnvironment是所有Flink程序的基础。可以通过以下静态方法获得:

    getExecutionEnvironment()
    
    createLocalEnvironment()
    
    createRemoteEnvironment(String host, int port, String... jarFiles)

    通常只需要使用getExecutionEnvironment()方法,因为这将根据环境做出正确的事:如果你执行你的程序在IDE上或着作为一个普通Java程序,它将创建一个本地环境,将在本地机器上执行程序。如果您从您的程序创建了一个JAR文件,并通过命令行调用它,Flink集群管理者将执行你的main方法并且getExecutionEnvironment()将返回一个在一个集群上执行程序的执行环境。

  • 用于指定数据源,执行环境有几个方法来从文件读取:你可以逐行阅读,像CSV文件,或者使用完全自定义数据输入格式。要读取一个文本文件的顺序,您可以使用:
    final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
    
    DataStream<String> text = env.readTextFile("file:///path/to/file");

    这将给你一个数据流,然后,您可以通过转换创建新的派生数据流。

  • 你可以通过调用DataStream数据转换方法转换。例如,一个map转换看起来像这样:
    DataStream<String> input = ...;
    
    DataStream<Integer> parsed = input.map(new MapFunction<String, Integer>() {
    @Override
    public Integer map(String value) {
    return Integer.parseInt(value);
    }
    });

    通过将原始集合中的每个字符串转换为整数,这将创建一个新的数据流。

  • 一旦你有了一个包含你的最终结果的数据流,通过创建一个sink可以把它写一个外部系统。这些是一些创建一个sink的的方法示例:
    writeAsText(String path)
    
    print()
  • 一旦你指定完整程序,你需要通过调用StreamExecutionEnvironment上的execute()去触发程序执行。根据ExecutionEnvironment的类型,执行将会被触发在你的本地机器上或提交程序在集群上执行。这个execute()方法返回一个JobExecutionResult,它包含执行时间和累加结果。

3.延迟计算

  • 所有Flink程序都是延迟执行的:当一个程序的main方法被执行时,数据加载和转换没有被立刻发生,相反,每个操作被创造,添加到该程序的计划里。当执行明确地被execute() 触发时这些操作被真正执行。

4.指定的keys

  • 一些转换(join, coGroup, keyBy, groupBy)要求的集合上定义的一个key。其他的转换(Reduce, GroupReduce, Aggregate, Windows)允许数据在被应用前通过一个key被分组。
  • 一个DataSet被分组:
    DataSet<...> input = // [...]
    DataSet<...> reduced = input
    .groupBy(/*define key here*/)
    .reduceGroup(/*do something*/);

    一个key在DataStream中被指定:

    DataStream<...> input = // [...]
    DataStream<...> windowed = input
    .keyBy(/*define key here*/)
    .window(/*window specification*/);

    Flink的数据模型不是基于 键值( key-value)对的。keys是虚拟的:他们被定义为实际数据的函数来引导分组操作符。

5.指定转换函数

  • 许多转换需要用户自定义函数。
  • 实现一个接口:
    class MyMapFunction implements MapFunction<String, Integer> {
    public Integer map(String value) { return Integer.parseInt(value); }
    };
    data.map(new MyMapFunction());
  • 匿名类:
    data.map(new MapFunction<String, Integer> () {
    public Integer map(String value) { return Integer.parseInt(value); }
    });
  • 需要用户定义函数的所有转换都可以将rich函数作为参数。相比:
    class MyMapFunction implements MapFunction<String, Integer> {
    public Integer map(String value) { return Integer.parseInt(value); }
    };

    可以写成:

    class MyMapFunction extends RichMapFunction<String, Integer> {
    public Integer map(String value) { return Integer.parseInt(value); }
    };

    像往常一样传递函数到map转换:

    data.map(new MyMapFunction());

    rich函数也可以被定义为一个匿名类:

    data.map (new RichMapFunction<String, Integer>() {
    public Integer map(String value) { return Integer.parseInt(value); }
    });

    rich函数除了提供像map一样的用户自定义功能外,还提供四个方法:openclosegetRuntimeContext, and setRuntimeContext。这些是有用的对于向函数传递参数,创建并最终确定本地状态,访问广播变量,和用于访问运行时信息,如累加器和计数器,和信息迭代。

6.支持的数据类型

  1. Java Tuples and Scala Case Classes:java元组和Scala case类    元组是包含固定数量的含有各种类型的字段的复合类型。

    DataStream<Tuple2<String, Integer>> wordCounts = env.fromElements(
    new Tuple2<String, Integer>("hello", 1),
    new Tuple2<String, Integer>("world", 2)); wordCounts.map(new MapFunction<Tuple2<String, Integer>, Integer>() {
    @Override
    public Integer map(Tuple2<String, Integer> value) throws Exception {
    return value.f1;
    }
    }); wordCounts.keyBy(0); // also valid .keyBy("f0")
  2. java POJOs:Java和Scala类被Flink作为一种特殊的POJO数据类型对待,并且类必须是public的,它必须有一个没有参数的公共构造函数,所有的字段是公共或必须通过getter和setter函数来访问,对于一个被叫做foo的字段,getter和setter函数必须命名为getFoo()setFoo()。
    public class WordWithCount {
    
        public String word;
    public int count; public WordWithCount() {} public WordWithCount(String word, int count) {
    this.word = word;
    this.count = count;
    }
    } DataStream<WordWithCount> wordCounts = env.fromElements(
    new WordWithCount("hello", 1),
    new WordWithCount("world", 2)); wordCounts.keyBy("word"); // key by field expression "word"
  3. Primitive Types   基本数据类型   Flink支持java和Scala基本数据类型。
  4. General class types  一般类类型   Flink支持许多Java和Scala类(API和自定义)。所有不确定为POJO类类型(参见上面的POJO需求)是Flink一般类类型。Flink将这些数据类型视为黑盒,无法访问其内容。
  5. Value    值类型通过实现org.apache.flinktypes.Value接口的读和写方法为那些操作提供定制代码。当通用串行化是效率无效率的时候使用值类型是合理的。一个例子是一个数据类型实现稀疏向量元素的数组。知道数组大多是零,一个可以用一个特殊的编码输出非零元素,而通用串行化只会写所有的数组元素。    Flink用预定义的值类型,对应于基本数据类型。 (ByteValueShortValueIntValueLongValueFloatValueDoubleValueStringValueCharValueBooleanValue)。这些值类型作为可变的基本数据类型的变量,其价值可以更改,允许程序员重用对象和减轻垃圾收集器的压力。
  6. Hadoop Writables
  7. Special Types

7.Accumulators & Counters

  • Accumulators有简单的结构包括添加操作和工作结束后可用的最后累积的结果。
  • 最简单的accumulator是counter:你可以用Accumulator.add(V value)方法使他自己增量。工作结束后Flink将合并所有部分结果并将结果发送给客户端。Accumulators在调试或你想很快知道关于你的数据更多的时候是有用的。
  • Flink有以下内置的Accumulators,每一个都实现了Accumulator接口:IntCounter,LongCounter, and IDoubleCounter。
  • 如何使用accumulators:                                                                                                                                                        首先你应该你想使用accumulator在用户定义的转换函数处必须创建一个accumulator对象(这里是一个计数器)。
    private IntCounter numLines = new IntCounter();

    第二,你必须注册accumulator对象,通常在rich函数的open()方法。在这里你也可以定义名字。

    getRuntimeContext().addAccumulator("num-lines", this.numLines);

    您现在可以在运算符函数任何地方使用这个accumulator,包括open()和close()方法。

    this.numLines.add(1);

    总的结果将被存储在从执行环境的execute()方法返回的JobExecutionResult对象中。

    myJobExecutionResult.getAccumulatorResult("num-lines")

    每个job中所有的accumulator共享一个命名空间,因此,您可以使用相同的accumulator在你的job的不同运算符函数中。Flink将内部合并(合)并具有相同名称的accumulator。

  • 一般的,accumulators的结果只有在这个job结束之后才是可用的。
  • Accumulator<V,R>是最灵活的:它定义了一个类型V用于值的增加,和最终结果类型R用于最终结果。

Apache Flink - 基本API概念的更多相关文章

  1. 【翻译】Flink Table Api & SQL —— 概念与通用API

    本文翻译自官网:https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/common.html Flink Tabl ...

  2. Apache Flink -Streaming(DataStream API)

    综述: 在Flink中DataStream程序是在数据流上实现了转换的常规程序. 1.示范程序 import org.apache.flink.api.common.functions.FlatMap ...

  3. 如何在 Apache Flink 中使用 Python API?

    本文根据 Apache Flink 系列直播课程整理而成,由 Apache Flink PMC,阿里巴巴高级技术专家 孙金城 分享.重点为大家介绍 Flink Python API 的现状及未来规划, ...

  4. Apache Flink 流处理实例

    维基百科在 IRC 频道上记录 Wiki 被修改的日志,我们可以通过监听这个 IRC 频道,来实时监控给定时间窗口内的修改事件.Apache Flink 作为流计算引擎,非常适合处理流数据,并且,类似 ...

  5. flink DataStream API使用及原理

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

  6. 【翻译】Flink Table Api & SQL —— Table API

    本文翻译自官网:Table API  https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/tableApi.ht ...

  7. Apache Flink 为什么能够成为新一代大数据计算引擎?

    众所周知,Apache Flink(以下简称 Flink)最早诞生于欧洲,2014 年由其创始团队捐赠给 Apache 基金会.如同其他诞生之初的项目,它新鲜,它开源,它适应了快速转的世界中更重视的速 ...

  8. 企业实践 | 如何更好地使用 Apache Flink 解决数据计算问题?

    业务数据的指数级扩张,数据处理的速度可不能跟不上业务发展的步伐.基于 Flink 的数据平台构建.运用 Flink 解决业务场景中的具体问题等随着 Flink 被更广泛的应用于广告.金融风控.实时 B ...

  9. Flink SQL 核心概念剖析与编程案例实战

    本次,我们从 0 开始逐步剖析 Flink SQL 的来龙去脉以及核心概念,并附带完整的示例程序,希望对大家有帮助! 本文大纲 一.快速体验 Flink SQL 为了快速搭建环境体验 Flink SQ ...

随机推荐

  1. spring源码(1)---idea基础环境搭建

    一.环境准备 1. jdk1.8.1 做java开发的这个应该能自己找到 2.gradle-4.9 https://services.gradle.org/distributions/ 没用过grad ...

  2. 使用HTML CSS制作简易三角形和旗帜

    HTML:     <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  3. [Vuex系列] - Actions的理解之我见

    Actions如何定义的 恕小端不才,对Action的总结如下: Action 可以提交mutation方法,通过mutation来改变state Action 函数可以接收一个context对象,通 ...

  4. SpringBoot mysql出现The server time zone value '�й���׼ʱ��' is unrecogni

    MySql :8.0.18 引入的mysql驱动: SpringBoot整合Mybatis的框架,在访问Controller的时候 : ava.sql.SQLException: The server ...

  5. SpringDataJPA第三天讲义

    第1章     Specifications动态查询 有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecif ...

  6. MyEclipse设置java文件每行字符数

    window->preferences->java->code style->formatter->edit->line wrapping->maximum ...

  7. python之新的开始

    Day 1-Morning     终于开通了新的博客(等待审核的过程用着备忘录敲...)~感谢几位大佬们愿意带我一起学习 大家一起加油!(苟富贵,勿相忘!/doge 哈哈哈) 初学python,以下 ...

  8. Linux 下DNS详解

    配置之前先了解一下bind DNS服务器软件:BIND是一种开源的DNS(Domain Name System)协议的实现,包含对域名的查询和响应所需的所有软件.它是互联网上最广泛使用的一种DNS服务 ...

  9. 用js刷剑指offer(顺时针打印数组)

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数 ...

  10. mysql运维相关

    1.为什么要分库分表(设计高并发系统的时候,数据库层面该如何设计)?用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?2.现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统 ...