Flink系列文章

  1. 第01讲:Flink 的应用场景和架构模型
  2. 第02讲:Flink 入门程序 WordCount 和 SQL 实现
  3. 第03讲:Flink 的编程模型与其他框架比较
  4. 第04讲:Flink 常用的 DataSet 和 DataStream API
  5. 第05讲:Flink SQL & Table 编程和案例
  6. 第06讲:Flink 集群安装部署和 HA 配置
  7. 第07讲:Flink 常见核心概念分析
  8. 第08讲:Flink 窗口、时间和水印
  9. 第09讲:Flink 状态与容错

关注公众号:大数据技术派,回复资料,领取1024G资料。

这一课时将介绍 Flink 中提供的一个很重要的功能:旁路分流器。

分流场景

我们在生产实践中经常会遇到这样的场景,需把输入源按照需要进行拆分,比如我期望把订单流按照金额大小进行拆分,或者把用户访问日志按照访问者的地理位置进行拆分等。面对这样的需求该如何操作呢?

分流的方法

通常来说针对不同的场景,有以下三种办法进行流的拆分。

Filter 分流

Filter 方法我们在第 04 课时中(Flink 常用的 DataSet 和 DataStream API)讲过,这个算子用来根据用户输入的条件进行过滤,每个元素都会被 filter() 函数处理,如果 filter() 函数返回 true 则保留,否则丢弃。那么用在分流的场景,我们可以做多次 filter,把我们需要的不同数据生成不同的流。

来看下面的例子:

复制代码

public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//获取数据源
List data = new ArrayList<Tuple3<Integer,Integer,Integer>>();
data.add(new Tuple3<>(0,1,0));
data.add(new Tuple3<>(0,1,1));
data.add(new Tuple3<>(0,2,2));
data.add(new Tuple3<>(0,1,3));
data.add(new Tuple3<>(1,2,5));
data.add(new Tuple3<>(1,2,9));
data.add(new Tuple3<>(1,2,11));
data.add(new Tuple3<>(1,2,13)); DataStreamSource<Tuple3<Integer,Integer,Integer>> items = env.fromCollection(data); SingleOutputStreamOperator<Tuple3<Integer, Integer, Integer>> zeroStream = items.filter((FilterFunction<Tuple3<Integer, Integer, Integer>>) value -> value.f0 == 0); SingleOutputStreamOperator<Tuple3<Integer, Integer, Integer>> oneStream = items.filter((FilterFunction<Tuple3<Integer, Integer, Integer>>) value -> value.f0 == 1); zeroStream.print(); oneStream.printToErr(); //打印结果 String jobName = "user defined streaming source"; env.execute(jobName); }

在上面的例子中我们使用 filter 算子将原始流进行了拆分,输入数据第一个元素为 0 的数据和第一个元素为 1 的数据分别被写入到了 zeroStream 和 oneStream 中,然后把两个流进行了打印。

可以看到 zeroStream 和 oneStream 分别被打印出来。

Filter 的弊端是显而易见的,为了得到我们需要的流数据,需要多次遍历原始流,这样无形中浪费了我们集群的资源。

Split 分流

Split 也是 Flink 提供给我们将流进行切分的方法,需要在 split 算子中定义 OutputSelector,然后重写其中的 select 方法,将不同类型的数据进行标记,最后对返回的 SplitStream 使用 select 方法将对应的数据选择出来。

我们来看下面的例子:

复制代码

public static void main(String[] args) throws Exception {

    StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

    //获取数据源

    List data = new ArrayList<Tuple3<Integer,Integer,Integer>>();

    data.add(new Tuple3<>(0,1,0));

    data.add(new Tuple3<>(0,1,1));

    data.add(new Tuple3<>(0,2,2));

    data.add(new Tuple3<>(0,1,3));

    data.add(new Tuple3<>(1,2,5));

    data.add(new Tuple3<>(1,2,9));

    data.add(new Tuple3<>(1,2,11));

    data.add(new Tuple3<>(1,2,13));

    DataStreamSource<Tuple3<Integer,Integer,Integer>> items = env.fromCollection(data);

    SplitStream<Tuple3<Integer, Integer, Integer>> splitStream = items.split(new OutputSelector<Tuple3<Integer, Integer, Integer>>() {

        @Override

        public Iterable<String> select(Tuple3<Integer, Integer, Integer> value) {

            List<String> tags = new ArrayList<>();

            if (value.f0 == 0) {

                tags.add("zeroStream");

            } else if (value.f0 == 1) {

                tags.add("oneStream");

            }

            return tags;

        }

    });

    splitStream.select("zeroStream").print();

    splitStream.select("oneStream").printToErr();

    //打印结果

    String jobName = "user defined streaming source";

    env.execute(jobName);

}

同样,我们把来源的数据使用 split 算子进行了切分,并且打印出结果。

但是要注意,使用 split 算子切分过的流,是不能进行二次切分的,假如把上述切分出来的 zeroStream 和 oneStream 流再次调用 split 切分,控制台会抛出以下异常。

复制代码

Exception in thread "main" java.lang.IllegalStateException: Consecutive multiple splits are not supported. Splits are deprecated. Please use side-outputs.

这是什么原因呢?我们在源码中可以看到注释,该方式已经废弃并且建议使用最新的 SideOutPut 进行分流操作。

SideOutPut 分流

SideOutPut 是 Flink 框架为我们提供的最新的也是最为推荐的分流方法,在使用 SideOutPut 时,需要按照以下步骤进行:

  • 定义 OutputTag
  • 调用特定函数进行数据拆分
    • ProcessFunction
    • KeyedProcessFunction
    • CoProcessFunction
    • KeyedCoProcessFunction
    • ProcessWindowFunction
    • ProcessAllWindowFunction

在这里我们使用 ProcessFunction 来讲解如何使用 SideOutPut:

复制代码

public static void main(String[] args) throws Exception {

    StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

    //获取数据源

    List data = new ArrayList<Tuple3<Integer,Integer,Integer>>();

    data.add(new Tuple3<>(0,1,0));

    data.add(new Tuple3<>(0,1,1));

    data.add(new Tuple3<>(0,2,2));

    data.add(new Tuple3<>(0,1,3));

    data.add(new Tuple3<>(1,2,5));

    data.add(new Tuple3<>(1,2,9));

    data.add(new Tuple3<>(1,2,11));

    data.add(new Tuple3<>(1,2,13));

    DataStreamSource<Tuple3<Integer,Integer,Integer>> items = env.fromCollection(data);

    OutputTag<Tuple3<Integer,Integer,Integer>> zeroStream = new OutputTag<Tuple3<Integer,Integer,Integer>>("zeroStream") {};

    OutputTag<Tuple3<Integer,Integer,Integer>> oneStream = new OutputTag<Tuple3<Integer,Integer,Integer>>("oneStream") {};

    SingleOutputStreamOperator<Tuple3<Integer, Integer, Integer>> processStream= items.process(new ProcessFunction<Tuple3<Integer, Integer, Integer>, Tuple3<Integer, Integer, Integer>>() {

        @Override

        public void processElement(Tuple3<Integer, Integer, Integer> value, Context ctx, Collector<Tuple3<Integer, Integer, Integer>> out) throws Exception {

            if (value.f0 == 0) {

                ctx.output(zeroStream, value);

            } else if (value.f0 == 1) {

                ctx.output(oneStream, value);

            }

        }

    });

    DataStream<Tuple3<Integer, Integer, Integer>> zeroSideOutput = processStream.getSideOutput(zeroStream);

    DataStream<Tuple3<Integer, Integer, Integer>> oneSideOutput = processStream.getSideOutput(oneStream);

    zeroSideOutput.print();

    oneSideOutput.printToErr();

    //打印结果

    String jobName = "user defined streaming source";

    env.execute(jobName);

}

可以看到,我们将流进行了拆分,并且成功打印出了结果。这里要注意,Flink 最新提供的 SideOutPut 方式拆分流是可以多次进行拆分的,无需担心会爆出异常。

总结

这一课时我们讲解了 Flink 的一个小的知识点,是我们生产实践中经常遇到的场景,Flink 在最新的版本中也推荐我们使用 SideOutPut 进行流的拆分。

关注公众号:大数据技术派,回复资料,领取1024G资料。

第10讲:Flink Side OutPut 分流的更多相关文章

  1. [ionic开源项目教程] - 第10讲 新闻详情页的用户体验优化

    目录 [ionic开源项目教程] 第1讲 前言,技术储备,环境搭建,常用命令 [ionic开源项目教程] 第2讲 新建项目,架构页面,配置app.js和controllers.js [ionic开源项 ...

  2. 第10讲- UI线程阻塞及其优化

    第10讲UI线程阻塞及其优化 .UI 阻塞demo (首先在activity_main.xml中放置两个button,分别命名为button1,button2) //首先设置一个button1用来进行 ...

  3. JVM基础系列第10讲:垃圾回收的几种类型

    我们经常会听到许多垃圾回收的术语,例如:Minor GC.Major GC.Young GC.Old GC.Full GC.Stop-The-World 等.但这些 GC 术语到底指的是什么,它们之间 ...

  4. 第10讲-Java集合框架

    第10讲 Java集合框架 1.知识点 1.1.课程回顾 1.2.本章重点 1.2.1 List 1.2.2 Set 1.2.3 Map 2.具体内容 2.1.Java集合框架 2.1.1 为什么需要 ...

  5. [VirtualBox] Install Ubuntu 14.10 error 5 Input/output error

    After you download the VirtualBox install package and install it (just defualt setting). Then you sh ...

  6. PHP学习之[第10讲]PHP 的 Mysql 数据库函数 (微型博客系统)II

    mysql结构如下: -- phpMyAdmin SQL Dump -- version 4.4.1.1 -- http://www.phpmyadmin.net -- -- Host: localh ...

  7. 《Tsinghua oc mooc》第8~10讲 虚拟内存管理

    资源 OS2018Spring课程资料首页 uCore OS在线实验指导书 ucore实验基准源代码 MOOC OS习题集 OS课堂练习 Piazza问答平台 暂时无法注册 第八讲 虚拟内存概念 为什 ...

  8. flink系列-10、flink保证数据的一致性

    本文摘自书籍<Flink基础教程> 一.一致性的三种级别 当在分布式系统中引入状态时,自然也引入了一致性问题.一致性实际上是“正确性级别”的另一种说法,即在成功处理故障并恢复之后得到的结果 ...

  9. 第10讲:利用SQL语言实现关系代数操作

    一.实现并.交.差运算 1. 基本语法形式:子查询 [union [all] | intersect [all] | except [all] 子查询] ①意义:将关系代数中的∪.∩.- 分别用uni ...

随机推荐

  1. Spring 处理请求和响应相关的注解

    @Controller 默认返回 templates 目录下的 string.html 页面内容. 在方法中加上 @ResponseBody 注解,可以返回JSON.XML或自定义mediaType的 ...

  2. Linux架构中代理服务器配置与负载均衡

    本期内容概要 代理 负载均衡 内容详细 1.代理 1.主要作用: 将流量平均分配 2.代理的方式 01 正向代理 外部想要访问服务器 先找代理 找到之后还需要找服务器 应用:VPN 02 反向代理 外 ...

  3. 我踩过的python的坑

    1. string中Template用法 变量名不能是${tradeDate+1}, python无法识别其为变量,应改为 ${tradeDate1} 变量替换的语句:data_new = Templ ...

  4. java 封装 总结

    1.前言 老是被问什么是java 封装...很基础的一个问题 ,其实我们一直在写的东西但不知道怎么称呼. 比如 在entity实体类 里面老用到的 getter 和 setter 方法其实就是封装的方 ...

  5. 微信小程序配置域名的时候提示“校验文件验证失败”

    在微信小程序后台配置web-view的业务域名跟扫普通链接二维码打开小程序两项功能时, 一直提示"校验文件验证失败,请下载校验文件,上传到服务器指定的目录" 实际访问校验文件的路径 ...

  6. kafka学习笔记(三)kafka的使用技巧

    概述 上一篇随笔主要介绍了kafka的基本使用包括集群参数,生产者基本使用,consumer基本使用,现在来介绍一下kafka的使用技巧. 分区机制 我们在使用 Apache Kafka 生产和消费消 ...

  7. 一文看懂B端产品和C端产品

    大纲 什么是B端产品 什么是C端产品 为什么会产生B端产品和C端产品 怎么判断一个产品是B端还是C端 B端产品和C端产品存在哪些差异 C端产品经理如何向B端产品经理转型 写在最后   什么是B, Bu ...

  8. leetcode 51. N皇后 及 52.N皇后 II

    51. N皇后 问题描述 n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n,返回所有不同的 n 皇后 ...

  9. 18个示例详解 Spring 事务传播机制(附测试源码)

    什么是事务传播机制 事务的传播机制,顾名思义就是多个事务方法之间调用,事务如何在这些方法之间传播. 举个例子,方法 A 是一个事务的方法,方法 A 执行的时候调用了方法 B,此时方法 B 有无事务以及 ...

  10. Java打印空心三角

    Java打印空心三角 public static void main(String[] args) { int n=5; //n表示输出空心三角形行数,这里以5行为例 for(int i=1;i< ...