Flink DataSet API编程指南

Flink最大的亮点是实时处理部分,Flink认为批处理是流处理的特殊情况,可以通过一套引擎处理批量和流式数据,而Flink在未来也会重点投入更多的资源到批流融合中。我在Flink DataStream API编程指南中介绍了DataStream API的使用,在本文中将介绍Flink批处理计算的DataSet API的使用。通过本文你可以了解:

  • DataSet转换操作(Transformation)
  • Source与Sink的使用
  • 广播变量的基本概念与使用Demo
  • 分布式缓存的概念及使用Demo
  • DataSet API的Transformation使用Demo案例

关注公众号:大数据技术与数仓
免费领取百G大数据视频、电子书资料
在这里插入图片描述

WordCount示例

在开始讲解DataSet API之前,先看一个Word Count的简单示例,来直观感受一下DataSet API的编程模型,具体代码如下:

public class WordCount {
   
    public static void main(String[] args) throws Exception {
   
        // 用于批处理的执行环境
        ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();

        // 数据源
        DataSource<String> stringDataSource = env.fromElements("hello Flink What is Apache Flink");

        // 转换
        AggregateOperator<Tuple2<String, Integer>> wordCnt = stringDataSource
                .flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
   
                    @Override
                    public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
   
                        String[] split = value.split(" ");
                        for (String word : split) {
   
                            out.collect(Tuple2.of(word, 1));
                        }
                    }
                })
                .groupBy(0)
                .sum(1);
        // 输出
        wordCnt.print();
    }
}

从上面的示例中可以看出,基本的编程模型是:

  • 获取批处理的执行环境ExecutionEnvironment
  • 加载数据源
  • 转换操作
  • 数据输出

下面会对数据源、转换操作、数据输出进行一一解读。

Data Source

DataSet API支持从多种数据源中将批量数据集读到Flink系统中,并转换成DataSet数据集。主要包括三种类型:分别是基于文件的、基于集合的及通用类数据源。同时在DataSet API中可以自定义实现InputFormat/RichInputFormat接口,以接入不同数据格式类型的数据源,比如CsvInputFormat、TextInputFormat等。从ExecutionEnvironment类提供的方法中可以看出支持的数据源方法,如下图所示:

在这里插入图片描述

基于文件的数据源

readTextFile(path) / TextInputFormat
  • 解释

读取文本文件,传递文件路径参数,并将文件内容转换成DataSet类型数据集。

  • 使用
// 读取本地文件
DataSet<String> localLines = env.readTextFile("file:///path/to/my/textfile");
// 读取HDSF文件
DataSet<String> hdfsLines = env.readTextFile("hdfs://nnHost:nnPort/path/to/my/textfile");
readTextFileWithValue(path)/ TextValueInputFormat
  • 解释

读取文本文件内容,将文件内容转换成DataSet[StringValue]类型数据集。该方法与readTextFile(String)不同的是,其泛型是StringValue,是一种可变的String类型,通过StringValue存储文本数据可以有效降低String对象创建数量,减小垃圾回收的压力。

  • 使用
// 读取本地文件
DataSet<StringValue> localLines = env.readTextFileWithValue("file:///some/local/file");
// 读取HDSF文件
DataSet<StringValue> hdfsLines = env.readTextFileWithValue("hdfs://host:port/file/path");
readCsvFile(path)/ CsvInputFormat
  • 解释

创建一个CSV的reader,读取逗号分隔(或其他分隔符)的文件。可以直接转换成Tuple类型、POJOs类的DataSet。在方法中可以指定行切割符、列切割符、字段等信息。

  • 使用
// read a CSV file with five fields, taking only two of them
// 读取一个具有5个字段的CSV文件,只取第一个和第四个字段
DataSet<Tuple2<String, Double>> csvInput = env.readCsvFile("hdfs:///the/CSV/file")
                               .includeFields("10010")  
	                          .types(String.class, Double.class);

// 读取一个有三个字段的CSV文件,将其转为POJO类型
DataSet<Person>> csvInput = env.readCsvFile("hdfs:///the/CSV/file")
                         .pojoType(Person.class, "name", "age", "zipcode");
readFileOfPrimitives(path, Class) / PrimitiveInputFormat
  • 解释

读取一个原始数据类型(如String,Integer)的文件,返回一个对应的原始类型的DataSet集合

  • 使用
DataSet<String> Data = env.readFileOfPrimitives("file:///some/local/file", String.class);

基于集合的数据源

fromCollection(Collection)
  • 解释

从java的集合中创建DataSet数据集,集合中的元素数据类型相同

  • 使用
DataSet<String> data= env.fromCollection(arrayList);
fromElements(T …)
  • 解释

从给定数据元素序列中创建DataSet数据集,且所有的数据对象类型必须一致

  • 使用
 DataSet<String> stringDataSource = env.fromElements("hello Flink What is Apache Flink");
generateSequence(from, to)
  • 解释

指定from到to范围区间,然后在区间内部生成数字序列数据集,由于是并行处理的,所以最终的顺序不能保证一致。

  • 使用
DataSet<Long> longDataSource = env.generateSequence(1, 20);

通用类型数据源

DataSet API中提供了Inputformat通用的数据接口,以接入不同数据源和格式类型的数据。InputFormat接口主要分为两种类型:一种是基于文件类型,在DataSet API对应readFile()方法;另外一种是基于通用数据类型的接口,例如读取RDBMS或NoSQL数据库中等,在DataSet API中对应createInput()方法。

readFile(inputFormat, path) / FileInputFormat
  • 解释

自定义文件类型输入源,将指定格式文件读取并转成DataSet数据集

  • 使用
env.readFile(new MyInputFormat(), "file:///some/local/file");

createInput(inputFormat) / InputFormat
  • 解释

自定义通用型数据源,将读取的数据转换为DataSet数据集。如以下实例使用Flink内置的JDBCInputFormat,创建读取mysql数据源的JDBCInput Format,完成从mysql中读取Person表,并转换成DataSet [Row]数据集

  • 使用
DataSet<Tuple2<String, Integer> dbData =
    env.createInput(
      JDBCInputFormat.buildJDBCInputFormat()
                     .setDrivername("com.mysql.jdbc.Driver")
                     .setDBUrl("jdbc:mysql://localhost/mydb")
                     .setQuery("select name, age from stu")
                     .setRowTypeInfo(new RowTypeInfo(BasicTypeInfo.STRING_TYPE_INFO, BasicTypeInfo.INT_TYPE_INFO))
                     .finish()
    );

Data Sink

Flink在DataSet API中的数据输出共分为三种类型。第一种是基于文件实现,对应DataSet的write()方法,实现将DataSet数据输出到文件系统中。第二种是基于通用存储介质实现,对应DataSet的output()方法,例如使用JDBCOutputFormat将数据输出到关系型数据库中。最后一种是客户端输出,直接将DataSet数据从不同的节点收集到Client,并在客户端中输出,例如DataSet的print()方法。

标准的数据输出方法

// 文本数据
DataSet<String> textData = // [...]

// 将数据写入本地文件
textData.writeAsText("file:///my/result/on/localFS");

// 将数据写入HDFS文件
textData.writeAsText("hdfs://nnHost:nnPort/my/result/on/localFS");

// 写数据到本地文件,如果文件存在则覆盖
textData.writeAsText("file:///my/result/on/localFS", WriteMode.OVERWRITE);

// 将数据输出到本地的CSV文件,指定分隔符为"|"
DataSet<Tuple3<String, Integer, Double>> values = // [...]
values.writeAsCsv("file:///path/to/the/result/file", "\n", "|");

// 使用自定义的TextFormatter对象
values.writeAsFormattedText("file:///path/to/the/result/file",
    new TextFormatter<Tuple2<Integer, Integer>>() {
   
        public String format (Tuple2<Integer, Integer> value) {
   
            return value.f1 + " - " + value.f0;
        }
    });

使用自定义的输出类型

DataSet<Tuple3<String, Integer, Double>> myResult = [...]

// 将tuple类型的数据写入关系型数据库
myResult.output(
    // 创建并配置OutputFormat
    JDBCOutputFormat.buildJDBCOutputFormat()
                    .setDrivername("com.mysql.jdbc.Driver")
                    .setDBUrl("jdbc:mysql://localhost/mydb")
                    .setQuery("insert into persons (name, age, height) values (?,?,?)")
                    .finish()
    );

DataSet转换

转换(transformations)将一个DataSet转成另外一个DataSet,Flink提供了非常丰富的转换操作符。具体使用如下:

Map

一进一出

  DataSource<String> source = env.fromElements("I", "like", "flink");
        source.map(new MapFunction<String, String>() {
   
            @Override
            // 将数据转为大写
            public String map(String value) throws Exception {
   
                return value.toUpperCase();
            }
        }).print();

FlatMap

输入一个元素,产生0个、1个或多个元素

stringDataSource
                .flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
   
                    @Override
                    public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
   
                        String[] split = value.split(" ");
                        for (String word : split) {
   
                            out.collect(Tuple2.of(word, 1));
                        }
                    }
                })
                .groupBy(0)
                .sum(</
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值