簡體   English   中英

Flink:Flink 是否支持抽象算子,可以處理不同數據流的公共字段?

[英]Flink: does Flink support abstract operator which can process different data streams with common fields?

假設我們有多個數據流並且它們共享一些共同的特征。

例如,我們有一個教師的 stream 和一個學生的 stream ,它們都有一個年齡字段。 如果我想從實時 stream 中找出最年長的學生或老師,我可以實現如下操作符。

public MaxiumAgeFunc extends RichMapFunction<Student,Integer> {
    int maxAge;

    @Override
    public void flatMap(Student s, Collector<Integer> collector) throws Exception {
        if(s.age > maxAge){
            maxAge = s.age;
        }
        collector.collect(maxAge);
    }
}

要找出最年長的Teacher ,我們需要實現一個類似的運算符,如下所示

public MaxiumAgeFunc extends RichMapFunction<Teacher,Integer> {
    int maxAge;

    @Override
    public void flatMap(Teacher t, Collector<Integer> collector) throws Exception {
        if(t.age > maxAge){
            maxAge = t.age;
        }
        collector.collect(maxAge);
    }
}

但實際上這兩個算子有共同的流程邏輯,所以我的想法是定義一個父 class,比如People

public class People{
    public Integer age;
}

那么StudentTeacher可以定義為他們的孩子class,也可以保留自己的字段。

public class Student extends People {
    public Integer grade;  // student grade
    ...
}
public class Student extends People {
    public Integer subject;  // the subject that teacher teaches
    ...
}

在這種情況下,我可以定義一個運算符,如下所示。

public MaxiumAgeFunc extends RichMapFunction<People,Integer> {
    int maxAge;

    @Override
    public void flatMap(People p, Collector<Integer> collector) throws Exception {
        if(t.age > maxAge){
            maxAge = p.age;
        }
        collector.collect(maxAge);
    }
}

但是當我嘗試使用這個算子來實現一個 Flink 執行拓撲時,由於數據類型不匹配,它無法工作。

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<Student> studentStream = env.addSource(...);
DataStream<Teacher> teacherStream = env.addSource(...);

studentStream.map(new MaxiumAgeFunc()).print();
teacherStream.map(new MaxiumAgeFunc()).print();

這是我的問題,是否可以為具有公共字段的輸入流創建一個抽象運算符?

這更像是一個 Java 而不是 Flink 問題:

你想要做的是讓MaxiumAgeFunc像這樣參數化

public MaxiumAgeFunc<T extends People> extends RichMapFunction<T, Integer> {
    int maxAge;

    @Override
    public void flatMap(T p, Collector<Integer> collector) throws Exception {
        if(t.age > maxAge){
            maxAge = p.age;
        }
        collector.collect(maxAge);
    }
}

然后像這樣使用它

studentStream.map(new MaxiumAgeFunc<>()).print();
teacherStream.map(new MaxiumAgeFunc<>()).print();

編輯:

btw your function is not working with checkpointing (so will produce wrong results upon recovery from a checkpoint) and I'd rather go with an aggregation function over the global window .

students
    .windowAll(GlobalWindows.create())
    .aggregate(new AggregateFunction<People, Integer, Integer>() {
        @Override
        public Integer createAccumulator() {
            return -1;
        }

        @Override
        public Integer add(People value, Integer accumulator) {
            return Math.max(value.age, accumulator);
        }

        @Override
        public Integer getResult(Integer accumulator) {
            return accumulator;
        }

        @Override
        public Integer merge(Integer a, Integer b) {
            return Math.max(a, b);
        }
    });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM