flink DataStream keyBy通过API

时间:2019-01-13 05:43:11

标签: apache-flink

我是Flink的新手,以下是流媒体模式字数:

//x is the stream of (word, 1)
val x: DataStream[(String, Int)] = text
  .flatMap(_.toLowerCase.split("\\W+")) 
  .map((_, 1))

//keyBy on the word field, what does the Tuple here mean in y   
val y: KeyedStream[(String, Int), Tuple] = x.keyBy(0)  

val z: DataStream[(String, Int)] = y.sum(1)

z.print

假设x("a", 1), ("b", 1), ("c",1),("a",1),("c",1),("c",1)的流 y会是什么样子(我不明白Tuple的含义),然后z会是什么样子?

1 个答案:

答案 0 :(得分:2)

当您指定keyBy(0)时,您将通过流中元组的第一个元素来对流进行键控,换句话说,您将通过单词字符串来对流进行键控。但是,编译器无法确定键是字符串,因此此版本的keyBy始终将键视为包含某些对象(即实际键)的元组。

如果将keyBy重写为keyBy(_._1),则编译器将能够推断出密钥类型,而y将是KeyedStream[(String, Int), String],应该会更好。

该流完成的键操作是对流进行分区,类似于SQL中的groupBy将表拆分为不相交的,不重叠的组的方式。因此,在这种情况下,流(“ a”,1),(“ b”,1),(“ c”,1),(“ a”,1),(“ c”,1),(“ c” ,1)在逻辑上分为三组:

("a",1), ("a",1)
("b",1)
("c",1), ("c",1), ("c",1)

然后,通过将每个组中所有元组中的第二个字段相加,对每一个进行计算sum(1)会减少(在映射/减少意义上)每一个。因此,(“ a”,1),(“ a”,1)变为(“ a”,2),依此类推。

与其使用z=y.sum(1),还不如更完整地理解为以下内容,这可能更容易

val z: DataStream[(String, Int)] = y.reduce(new ReduceFunction[(String, Int)] {
  override def reduce(t1: (String, Int), t2: (String, Int)): (String, Int) =
    (t1._1, t1._2 + t2._2)
})

如果您运行代码,则可以准确看到z的样子。如果为其提供足够的资源,它可以在三个单独的线程中运行(因为有三个不同的键)。我刚才得到了这些结果:

3> (a,1)
2> (c,1)
1> (b,1)
2> (c,2)
2> (c,3)
3> (a,2)

其中1>,2>和3>指示哪个线程负责该行输出。