Apache flink 过滤ApacheFlink中的唯一事件

Apache flink 过滤ApacheFlink中的唯一事件,apache-flink,flink-streaming,Apache Flink,Flink Streaming,我在一个java类中定义某些变量,并使用另一个类访问它,以便过滤流中的唯一元素。请参考代码以更好地理解问题 我面临的问题是这个过滤函数不能很好地工作,不能过滤唯一的事件。我怀疑这个变量是在不同线程之间共享的,这就是原因!?如果这不是正确的方法,请建议另一种方法。提前谢谢 **ClassWithVariables.java** public static HashMap<String, ArrayList<String>> uniqueMap = new HashMap&l

我在一个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;
       }

}
**ClassWithVariables.java**
public static HashMap uniqueMap=new HashMap();
**FilterClass.java**
公共布尔筛选器(字符串val)引发异常{
if(ClassWithVariables.uniqueMap.containsKey(键)){
Arraylist al=uniqueMap.get(key);
如果(al)包含(val){
返回false;
}否则{
//更新hashmap列表(uniqueMap)
返回true;
}
}否则{
//添加到hashmap列表(uniqueMap)
返回true;
}
}

消除流重复的正确方法包括按密钥对流进行分区,以便包含相同密钥的所有元素将由同一个工作进程处理,并使用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);
    }
  }
}
publicstaticvoidmain(字符串[]args)引发异常{
StreamExecutionEnvironment env=StreamExecutionEnvironment.getExecutionEnvironment();
env.addSource(新的EventSource())
.keyBy(e->e.key)
.flatMap(新的重复数据消除())
.print();
execute();
}
公共静态类重复数据消除扩展了RichFlatMapFunction{
所见的价值状态;
@凌驾
公共无效打开(配置配置){
ValueStateDescriptor desc=新的ValueStateDescriptor(“seen”,Types.BOOLEAN);
seen=getRuntimeContext().getState(desc);
}
@凌驾
公共void flatMap(事件、收集器输出)引发异常{
if(seen.value()==null){
收集(事件);
见。更新(真);
}
}
}
顺便说一句,这也可以实现为RichFilterFunction。但是请注意,如果您有一个无限的密钥空间,则使用的状态将无限增长,直到堆或磁盘上的空间用完为止,具体取决于您选择的Flink状态后端。如果这是一个问题,您可能希望通过设置状态保留策略


还请注意,在Flink管道的不同部分之间共享状态是不可能的。与看起来正常的情况相比,您需要将内容从内到外转换,并使事件流进入状态,而不是获取它。

消除重复流的正确方法是按键对流进行分区,以便所有元素都包含相同的密钥将由同一个工作者处理,并使用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);
    }
  }
}
publicstaticvoidmain(字符串[]args)引发异常{
StreamExecutionEnvironment env=StreamExecutionEnvironment.getExecutionEnvironment();
env.addSource(新的EventSource())
.keyBy(e->e.key)
.flatMap(新的重复数据消除())
.print();
execute();
}
公共静态类重复数据消除扩展了RichFlatMapFunction{
所见的价值状态;
@凌驾
公共无效打开(配置配置){
ValueStateDescriptor desc=新的ValueStateDescriptor(“seen”,Types.BOOLEAN);
seen=getRuntimeContext().getState(desc);
}
@凌驾
公共void flatMap(事件、收集器输出)引发异常{
if(seen.value()==null){
收集(事件);
见。更新(真);
}
}
}
顺便说一句,这也可以实现为RichFilterFunction。但是请注意,如果您有一个无限的密钥空间,则使用的状态将无限增长,直到堆或磁盘上的空间用完为止,具体取决于您选择的Flink状态后端。如果这是一个问题,您可能希望通过设置状态保留策略


还请注意,在Flink管道的不同部分之间共享状态是不可能的。与看起来正常的情况相比,您需要将事情由内而外,并将事件流带到状态,而不是获取它。

谢谢David的回答。谢谢David的回答。