ビッグデータ (9e) Flink サイド出力ストリーム

概要

The window allow late data, but still data received after the window is closed.
Flink は、ウィンドウが閉じられた後に到着するデータを処理するための副出力ストリーム(sideOutput) を提供します。

環境

WIN10+アイデア+JDK1.8+FLINK1.14

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <flink.version>1.14.6</flink.version>
    <scala.binary.version>2.12</scala.binary.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-java</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-streaming-java_${scala.binary.version}</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-clients_${scala.binary.version}</artifactId>
        <version>${flink.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.flink</groupId>
        <artifactId>flink-runtime-web_${scala.binary.version}</artifactId>
        <version>${flink.version}</version>
    </dependency>
</dependencies>

OutputTag の概要

出力タグ演算子の副出力をマークするために使用される名前付きトークンです

シャントを実現

ctx.output:向由OutputTag标识的侧输出发出记录

import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.ProcessFunction;
import org.apache.flink.util.Collector;
import org.apache.flink.util.OutputTag;

public class Hi {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //创建执行环境,设置并行度
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment().setParallelism(1);
        //定义输出标签
        OutputTag<Integer> o1 = new OutputTag<Integer>("除以3余1") {
    
    };
        OutputTag<Integer> o2 = new OutputTag<Integer>("除以3余2") {
    
    };
        //创建流
        SingleOutputStreamOperator<Integer> d = env.fromElements(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        //处理
        SingleOutputStreamOperator<Integer> s = d.process(new ProcessFunction<Integer, Integer>() {
    
    
            @Override
            public void processElement(Integer value, Context ctx, Collector<Integer> out) {
    
    
                //分流
                if (value % 3 == 2) {
    
    
                    ctx.output(o2, value); //ctx.output:向由OutputTag标识的侧输出发出记录
                } else if (value % 3 == 1) {
    
    
                    ctx.output(o1, value); //ctx.output:向由OutputTag标识的侧输出发出记录
                } else {
    
    
                    out.collect(value);
                }
            }
        });
        //输出
        s.print("被3整除");
        s.getSideOutput(o1).print(o1.getId());
        s.getSideOutput(o2).print(o2.getId());
        //环境执行
        env.execute();
    }
}
試験結果
3 で割り切れる > 0 で
余り 1 > 1
で 3 余り 2 > 2
で 3 > 3
で 3 余り 1 > 4
で 3 余り 2 > 5 で
3 で割る > 6
で 3 余り 1 > 7
3 で割ると余り 2 > 8 は
3 > 9 で割り切れます

遅延データの処理

import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.ProcessFunction;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.streaming.api.watermark.Watermark;
import org.apache.flink.util.Collector;
import org.apache.flink.util.OutputTag;

public class Hi {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //创建执行环境,设置并行度
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment().setParallelism(1);
        //定义测输出流的输出标签
        OutputTag<String> outputTag = new OutputTag<String>("迟到标签") {
    
    };
        //创建流,添加自定义数据源
        SingleOutputStreamOperator<String> d = env.addSource(new SourceFunction<String>() {
    
    
            @Override
            public void run(SourceContext<String> ctx) {
    
    
                //发送水位线
                ctx.emitWatermark(new Watermark(1999L));
                //发送2条数据,其中1条迟到
                ctx.collectWithTimestamp("1998", 1998L);
                ctx.collectWithTimestamp("2000", 2000L);
            }
            @Override
            public void cancel() {
    
    }
        });
        //处理
        SingleOutputStreamOperator<String> s = d.process(new ProcessFunction<String, String>() {
    
    
            @Override
            public void processElement(String value, Context ctx, Collector<String> out) {
    
    
                //获取水位线
                long watermark = ctx.timerService().currentWatermark();
                //判断是否迟到
                if (ctx.timestamp() > watermark) {
    
    
                    //冇迟到
                    out.collect(value);
                } else {
    
    
                    //迟到:向outputTag发送数据
                    ctx.output(outputTag, value);
                }
            }
        });
        //输出
        s.print("主流输出");
        s.getSideOutput(outputTag).print("侧输出");
        //环境执行
        env.execute();
    }
}
1999 年の水位を送信し、次に 2 つのデータを送信すると、テスト結果は次のようになります。
副産出 > 1998年
主流産出 > 2000年

ウィンドウが閉じられた後に到着するデータを処理する

窓を開けた後.sideOutputLateData(outputTag)

import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.streaming.api.watermark.Watermark;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.OutputTag;

public class Hi {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //创建执行环境,设置并行度
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment().setParallelism(1);
        //定义测输出流的输出标签
        OutputTag<String> outputTag = new OutputTag<String>("迟到标签") {
    
    };
        //创建流,添加自定义数据源
        SingleOutputStreamOperator<String> d = env.addSource(new SourceFunction<String>() {
    
    
            @Override
            public void run(SourceContext<String> ctx) {
    
    
                ctx.collectWithTimestamp("a", 4000L);
                ctx.collectWithTimestamp("b", 5000L);
                ctx.emitWatermark(new Watermark(5999L)); //发送水位线,触发【3000~5999】的窗口关闭
                ctx.collectWithTimestamp("c", 5000L);
                ctx.collectWithTimestamp("d", 5000L);
                ctx.collectWithTimestamp("e", 6000L);
                ctx.collectWithTimestamp("f", 7000L);
            }
            @Override
            public void cancel() {
    
    }
        });
        //处理
        SingleOutputStreamOperator<String> s = d
                //事件时间滚动窗口
                .windowAll(TumblingEventTimeWindows.of(Time.seconds(3L)))
                //侧输出
                .sideOutputLateData(outputTag)
                //拼接字符串
                .reduce((a, b) -> a + "," + b);
        //输出
        s.print("主流输出");
        s.getSideOutput(outputTag).print("侧输出");
        //环境执行
        env.execute();
    }
}
中央の水位線を送信し、ウィンドウを閉じるようにトリガーします。テスト結果は次のとおりです
本流出力 > a, b
側出力 > c
側出力 > d
本流出力 > e, f

おすすめ

転載: blog.csdn.net/Yellow_python/article/details/128116908