在Apache Flink中过滤唯一事件

时间:2019-07-05 06:08:24

标签: apache-flink flink-streaming

我在一个Java类中定义了某些变量,并用另一个类来访问它,以便为唯一元素过滤流。请参考代码以更好地了解问题。

我面临的问题是此筛选器功能无法正常运行,并且无法筛选唯一事件。我怀疑该变量在不同线程之间共享,这是原因!如果这不是正确的方法,请提出另一种方法。预先感谢。

**ClassWithVariables.java**
public static HashMap<String, ArrayList<String>> uniqueMap = new HashMap<>();


**FilterClass.java**
public boolean filter(String val) throws Exception {

       if(ClassWithVariables.uniqueMap.containsKey(key)) {

                Arraylist<String> al = uniqueMap.get(key);

                if(al.contains(val) {
                    return false;
                } else {
                    //Update the hashmap list(uniqueMap)                    
                    return true;    
                }


       } else {

               //Add to hashmap list(uniqueMap)
               return true;
       }

}

1 个答案:

答案 0 :(得分:0)

对流进行重复数据删除的正确方法包括通过密钥对流进行分区,以便包含相同密钥的所有元素都将由同一工作人员处理,并使用flink的托管,键控状态机制,以使状态为故障宽容和可伸缩。这是一个示例实现:

public static void main(String[] args) throws Exception {
  StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

  env.addSource(new EventSource())
    .keyBy(e -> e.key)
    .flatMap(new Deduplicate())
    .print();

  env.execute();
}

public static class Deduplicate extends RichFlatMapFunction<Event, Event> {
  ValueState<Boolean> seen;

  @Override
  public void open(Configuration conf) {
    ValueStateDescriptor<Boolean> desc = new ValueStateDescriptor<>("seen", Types.BOOLEAN);
    seen = getRuntimeContext().getState(desc);
  }

  @Override
  public void flatMap(Event event, Collector<Event> out) throws Exception {
    if (seen.value() == null) {
      out.collect(event);
      seen.update(true);
    }
  }
}

这也可以实现为RichFilterFunction,btw。但是请注意,如果您拥有无限制的密钥空间,则使用的状态将无限期增长,直到耗尽堆空间或磁盘上的空间为止,这取决于您选择的Flink的状态后端。如果这是一个问题,则可能要通过State Time-to-Live设置状态保留策略。

还请注意,无法在Flink管道的不同部分之间共享状态。与看似正常的情况相比,您需要将事情从内到外翻转,并将事件流带入状态,而不是获取事件流。