window 运营商行为澄清后的 Apache Flink KeyedStream

Apache Flink KeyedStream after window operator behavior clarification

我要求澄清 Apache Flink (1.6.0) 在通过 window 和一些运算符(例如 reduce() 或 process())发送事件后如何处理来自 KeyedStreams 的事件) 已应用。

假设一个单节点集群,在一个键控 windowed 流上的操作符被执行后,剩下恰好 1 个数据流或恰好 k 个数据流(其中 k 是键的唯一值的数量)?

为澄清起见,考虑需要从某些来源读取事件,通过某些 k 进行键控,将键控事件发送到某些 windowed 流中,减少,然后然后做其他任何事情。下面两张图中的哪一张会被实际构建出来?

图 A

                     |--------------|
                     |    source    |
                     | (DataStream) |
                     |--------------|
                            |
                       [all events]
                            |
                            v
                     |--------------|
                     |  key by( k ) |
                     | (KeyedStream)|
                     |--------------|
                   /         |        \
                 /           |          \
            [ k = 1 ]    [ k = 2 ]    [ k = 3 ]
             /               |               \
           /                 |                 \
         v                   v                   v
|------------------||------------------||------------------|
|  sliding window  ||  sliding window  ||  sliding window  |
| (WindowedStream) || (WindowedStream) || (WindowedStream) |
|------------------||------------------||------------------|
         |                   |                   |
     [ k = 1 ]           [ k = 2 ]           [ k = 3 ]
         |                   |                   |
         v                   v                   v
   |----------|        |----------|        |----------|
   |  reduce  |        |  reduce  |        |  reduce  |
   |----------|        |----------|        |----------|
         |                   |                   |
     [ k = 1 ]           [ k = 2 ]           [ k = 3 ]
         |                   |                   |
         v                   v                   v
  |--------------|    |--------------|    |--------------|
  |     foo      |    |     foo      |    |     foo      |
  | (DataStream) |    | (DataStream) |    | (DataStream) |
  |--------------|    |--------------|    |--------------|

图 B

                     |--------------|
                     |    source    |
                     | (DataStream) |
                     |--------------|
                            |
                       [all events]
                            |
                            v
                     |--------------|
                     |  key by( k ) |
                     | (KeyedStream)|
                     |--------------|
                   /         |        \
                 /           |          \
            [ k = 1 ]    [ k = 2 ]    [ k = 3 ]
             /               |               \
           /                 |                 \
         v                   v                   v
|------------------||------------------||------------------|
|  sliding window  ||  sliding window  ||  sliding window  |
| (WindowedStream) || (WindowedStream) || (WindowedStream) |
|------------------||------------------||------------------|
         |                   |                   |
     [ k = 1 ]           [ k = 2 ]           [ k = 3 ]
         |                   |                   |
         v                   v                   v
   |----------|        |----------|        |----------|
   |  reduce  |        |  reduce  |        |  reduce  |
   |----------|        |----------|        |----------|
         \                   |                  /
            \                |                /
               \             |             /
                  \          |          /
                     \       |       /
                        \    |    /
                           \ | /
                       [all products]
                             |
                             v
                      |--------------|
                      |     foo      |
                      | (DataStream) |
                      |--------------|

编辑 (2018-09-22)

根据 David 的回答,我认为我误解了 KeyedStreams 与 window 或其他流结合使用的确切方式。不知何故,我得到的印象是 KeyedStream 通过在幕后创建多个流来对传入流进行分区,而不是仅仅使用相同的流按某个值将对象分组在一起。

我认为 Flink 的作用相当于:

List<Foo> eventsForKey1 = ...;
List<Foo> eventsForKey2 = ...;
List<Foo> eventsForKey3 = ...;
...
List<Foo> eventsForKeyN = ...;

我现在看到 Flink 实际上做的相当于:

Map<Key, List<Foo>> events = ...;

探索作业图在各种情况下的样子的最佳方法是编写一些简单的应用程序并在 Flink 附带的仪表板中检查它们的作业图。

我不确定如何解释您在 keyBy 之后显示的扇出,这使得回答您的问题变得困难。如果您询问生成的 foo DataStream 的并行性,它可以是任何您想要的。

如果 keyBy 之前和之后的并行度均为 1,则流将不会像您所显示的那样被拆分。相反,将有一个 Window 运算符来处理所有键。 (并行性与键的数量无关,尽管键控运算符——例如滑动 window 及其 reduce 函数——不能利用大于键数的并行性。)

但即使在单个节点中,您也可以拥有多个核心,并将 window 运算符的并行度设置为 3。如果是这样的话,reduce 函数的结果可以由后续运算符并行处理你要。但是不管并行度如何,你的那部分工作将只有一个 DataStream (foo)。

如果我误解了问题,请更新您的问题,我会再试一次。

认为 你真正想问的是你是否在 reduce 操作之后得到了 KeyedStream。如果是这样,那么答案是否定的,你会得到一个常规的 DataStream.

尽管可以通过 DataStreamUtils.reinterpretAsKeyedStream(DataStream, KeySelector) 将其转换回 KeyedStream,但前提是您小心确保没有更改用于创建的字段值window.

的键