Joh*_*one 5 partitioning topography sliding-window apache-flink flink-streaming
我请求澄清 Apache Flink (1.6.0) 在事件通过窗口发送并应用了某些运算符(例如 reduce() 或 process())后如何处理来自 KeyedStreams 的事件。
假设一个单节点集群,在对键控窗口流执行操作后,是否只剩下 1 个数据流或k 个数据流(其中k是键的唯一值的数量)?
为了澄清起见,考虑需要从某个源读取事件,按某个k键,将键控事件发送到某个窗口流中,减少,然后执行几乎所有其他操作。下面两张图中哪一张实际上会被构建出来?
图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) |
|--------------| |--------------| |--------------|
Run Code Online (Sandbox Code Playgroud)
图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) |
|--------------|
Run Code Online (Sandbox Code Playgroud)
编辑 (2018-09-22)
根据 David 的回答,我认为我误解了 KeyedStreams 与窗口或其他流结合使用的确切方式。不知何故,我的印象是 KeyedStream 通过在幕后创建多个流来分区传入流,而不是仅使用同一流按某个值将对象分组在一起。
我认为 Flink 所做的相当于:
List<Foo> eventsForKey1 = ...;
List<Foo> eventsForKey2 = ...;
List<Foo> eventsForKey3 = ...;
...
List<Foo> eventsForKeyN = ...;
Run Code Online (Sandbox Code Playgroud)
我现在看到 Flink 实际上做了相当于:
Map<Key, List<Foo>> events = ...;
Run Code Online (Sandbox Code Playgroud)
探索各种场景下作业图的最佳方式是编写一些简单的应用程序,并在 Flink 附带的仪表板中检查它们的作业图。
我不确定如何解释您在 keyBy 之后显示的扇出,这使得回答您的问题变得困难。如果您询问生成的 foo DataStream 的并行性,它可以是您想要的任何值。
如果 keyBy 之前和之后的并行度均为 1,则流不会像您所示的那样被分割。相反,将有一个 Window 操作符来处理所有键。(并行度与键的数量无关,尽管键控运算符(例如滑动窗口及其归约函数)无法利用大于键数量的并行度。)
但即使在单个节点中,您也可以拥有多个核心并将窗口运算符的并行度设置为 3。并且如果您想要的话,reduce 函数的结果可以由后续运算符并行处理。但无论并行性如何,这部分工作都将只有一个 DataStream (foo)。
如果我误解了您的问题,请更新您的问题,我会再试一次。