Flink实战-旁路输出(SideOutput)的使用

本文介绍了Flink中旁路输出(SideOutput)的概念及其实战应用,通过示例展示了如何利用SideOutput对数据流进行分割处理,实现数据分流而不复制数据流。此外,还详细解释了旁路输出的编程范式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flink的旁路输出(SideOutput)实战

概述

旁路输出在Flink中叫作SideOutput,用途类似于DataStream#split,本质上是一个数据流的切分行为,按照条件将DataStream切分为多个子数据流,子数据流叫作旁路输出数据流,每个旁路输出数据流可以有自己的下游处理逻辑。

                         旁路输出
[读取数据]---->[处理逻辑1]---------->[数据输出]---->[HDFS]
                       \--------->[数据输出]----->[mysql]
                        \-------->[数据输出]----->[clickhouse]

旁路输出数据流的元素的数据类型可以与上游数据流不同,多个旁路输出数据流的数据类型也不必相同。

旁路输出的作用

  1. 对数据流进行分割,但又不会复制数据流的一种分流机制。
  2. 对延迟迟到的数据进行处理,这样就可以不用丢弃迟到的数据。
  3. 能有效解决Split算子不能进行连续分流的问题。

实战

public class SideOutputBaseUse {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStream<Integer> input = env.fromElements(1, 2, 3,4,5,6,7,8);

        // 定义旁路输出的tag,旁路输出时会绑定该tag。这里需要定义tag的名称。
        final OutputTag<String> sideOutputTag1 = new OutputTag<String>("sideOutput1") {};
        final OutputTag<String> sideOutputTag2 = new OutputTag<String>("sideOutput2") {};

        // 处理数据时,输出到一个或多个侧输出流
        SingleOutputStreamOperator<Integer> mainDataStream = input.process(
                new ProcessFunction<Integer, Integer>() {
                    @Override
                    public void processElement(Integer value,
                                               Context ctx,
                                               Collector<Integer> out) throws Exception {
                        // 发出数据到常规输出
                        out.collect(value);

                        // 发出数据到侧流tag: sideOutputTag1
                        ctx.output(sideOutputTag1, "sideout1-" + String.valueOf(value));

                        // 发出数据到侧流tag: sideOutputTag2
                        ctx.output(sideOutputTag2, "sideout2-" + String.valueOf(value));
                    }
                }
        );

        // 侧输出流1: 进行过滤,然后输出
        mainDataStream.getSideOutput(sideOutputTag1).filter(
                new FilterFunction<String>() {
                    @Override
                    public boolean filter(String s) throws Exception {
                        if (s.endsWith("2")) {
                            return false;
                        }
                        return true;
                    }
                }
        ).print("sideoutTagStream1");
        
        // 侧输出流2: 直接打印
        mainDataStream.getSideOutput(sideOutputTag2).print("sideoutTagStream2");

        env.execute("test side output");
    }
}

以上代码的输出:

sideoutTagStream1:5> sideout1-1
sideoutTagStream2:5> sideout2-1
sideoutTagStream1:4> sideout1-8
sideoutTagStream1:3> sideout1-7
sideoutTagStream1:7> sideout1-3
sideoutTagStream1:2> sideout1-6
sideoutTagStream2:2> sideout2-6
sideoutTagStream2:6> sideout2-2
sideoutTagStream1:8> sideout1-4
sideoutTagStream2:8> sideout2-4
sideoutTagStream2:7> sideout2-3
sideoutTagStream2:3> sideout2-7
sideoutTagStream2:4> sideout2-8
sideoutTagStream1:1> sideout1-5
sideoutTagStream2:1> sideout2-5

这里要注意的是,定义好OutputTag之后,只有在特定的函数中才能使用旁路输出,如下:

1)ProcessFunction;

2)KeyedProcessFunction;

3)CoProcessFunction;

4)ProcessWindowFunction;

5)ProcessAllWindowFunction;

6)ProcessJoinFunction;

7)KeyedCoProcessFunction。

只有在上述函数中才可以通过Context上下文对象,向OutputTag定义的旁路中输出emit数据。

旁路输出编程范式

从以上实战的代码可以看出:旁路输出的数据(DataStream)可以被下游获取,还可以将旁路输出DataStream当作一般的DataStream进行处理。

从以上代码可以看出侧输出流的通用代码框架如下:

  1. 第1步:定义侧输出流的outputTag
final OutputTag<String> sideOutputTag1 = new OutputTag<String>("sideOutput1") {};
  1. 第2步:把主处理流程的流输出到侧输出流的Tag中(相当于与定义的outputTag绑定)
ctx.output(sideOutputTag1, "sideout1-" + String.valueOf(value));

注意:这一步是在ProcessFunction等函数中进行的。

  1. 第3步:获取已绑定的outputTag
mainDataStream.getSideOutput(sideOutputTag1).xxx

这样可以获取一个DataStream对象

  1. 第4步:对不同的侧输出流进行不同的处理,或则sink到不同的地方。
xxx.addsink(xxx);

也可以这样写。

总结

旁路输出是在不复制数据流的情况下。把一个数据流分割成多个流,并且不同的流进行不同的处理。通过这种方式来同一个流进行不同的处理非常方便,也是非常常用的一种流处理策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值