Apache flink ApacheFlink数据流API没有';我没有映射分区转换

Apache flink ApacheFlink数据流API没有';我没有映射分区转换,apache-flink,Apache Flink,Spark DStream有mapPartitionAPI,而FlinkDataStreamAPI没有。有没有人可以帮忙解释原因。我想做的是在Flink上实现一个类似于SparkreduceByKey的API。Flink的流处理模型与以小批量为中心的Spark Streaming非常不同。在Spark Streaming中,每个小批量都像在有限数据集上的常规批处理程序一样执行,而Flink DataStream程序则连续处理记录 在Flink的DataSet API中,MapPartitionF

Spark DStream有
mapPartition
API,而Flink
DataStream
API没有。有没有人可以帮忙解释原因。我想做的是在Flink上实现一个类似于Spark
reduceByKey
的API。

Flink的流处理模型与以小批量为中心的Spark Streaming非常不同。在Spark Streaming中,每个小批量都像在有限数据集上的常规批处理程序一样执行,而Flink DataStream程序则连续处理记录

在Flink的DataSet API中,
MapPartitionFunction
有两个参数。用于输入的迭代器和用于函数结果的收集器。Flink DataStream程序中的
MapPartitionFunction
永远不会从第一次函数调用返回,因为迭代器将遍历无穷无尽的记录流。然而,Flink的内部流处理模型要求用户函数返回以检查函数状态。因此,DataStream API不提供
mapPartition
转换

为了实现与Spark Streaming的reduceByKey类似的功能,您需要在流上定义一个键控窗口。Windows将流离散化,这有点类似于小批量,但Windows提供了更大的灵活性。由于窗口大小有限,因此可以调用
reduce
窗口

这可能看起来像:

yourStream.keyBy("myKey") // organize stream by key "myKey"
          .timeWindow(Time.seconds(5)) // build 5 sec tumbling windows
          .reduce(new YourReduceFunction); // apply a reduce function on each window
显示了如何定义各种窗口类型,并解释了所有可用的函数


注意:最近对DataStream API进行了修改。该示例假定最新版本(0.10-SNAPSHOT)将在未来几天内发布为0.10.0。

假定您的输入流是单分区数据(比如字符串)


Flink流媒体是纯流媒体(不是分批流媒体)。看看Iterate API。

您提供的“reduceByKey”解决方案似乎与spark中的“GroupByKey”类似,而不是“reduceByKey”。不,Flink的
reduce()
与Spark的
reduceByKey
一个组上的成对reduce函数一样适用。不过组定义有点不同,因为Flink在小批量中使用windows和Spark键值对。Flink中没有直接等效于Spark的
groupByKey
,因为这意味着整个组需要在内存中具体化,这可能导致OutOfMemoryErrors并杀死JVM。Flink提供了
groupReduce()
来使用流式迭代器。我看到Flink的reduce()应用了combinable。Flink DataStream没有reduceGroup API作为mapPartition的原因是否类似?是和否:-)。对于非窗口流,是的,因为它们是无限长的,
groupReduce
方法将永远不会返回。不适用于窗口流(窗口长度有限),其中
apply()
方法本质上是一个
groupReduce
函数,它还提供了一些窗口元数据。谢谢,我似乎找不到您提到的这种apply方法。
val new_number_of_partitions = 4

//below line partitions your data, you can broadcast data to all partitions
val step1stream = yourStream.rescale.setParallelism(new_number_of_partitions)

//flexibility for mapping
val step2stream = step1stream.map(new RichMapFunction[String, (String, Int)]{
  // var local_val_to_different_part : Type = null
  var myTaskId : Int = null

  //below function is executed once for each mapper function (one mapper per partition)
  override def open(config: Configuration): Unit = {
    myTaskId = getRuntimeContext.getIndexOfThisSubtask
    //do whatever initialization you want to do. read from data sources..
  }

  def map(value: String): (String, Int) = {
    (value, myTasKId)
  }
})

val step3stream = step2stream.keyBy(0).countWindow(new_number_of_partitions).sum(1).print
//Instead of sum(1), you can use .reduce((x,y)=>(x._1,x._2+y._2))
//.countWindow will first wait for a certain number of records for perticular key
// and then apply the function