我要求澄清Apache Flink(1.6.0)在通过窗口发送事件后如何处理来自KeyedStreams的事件,并且已经应用了一些运算符(例如reduce()或process()) .
假设单个节点集群在执行了键控窗口流上的运算符之后,剩下的只有1个DataStream或者恰好是k个DataStream(其中k是键的唯一值的数量)?
为了澄清,考虑需要从某些来源读取事件,通过某些k键,将键控事件发送到某个窗口流,减少,然后再做其他任何事情 . 实际构建下面两张图中的哪一幅?
Graph 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) |
|--------------| |--------------| |--------------|
Graph 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) |
|--------------|
Edit (2018-09-22)
根据David的回答,我认为我误解了KeyedStreams与窗口或其他流的结合 . 不知何故,我得到的印象是KeyedStream通过在幕后创建多个流来分区传入流,而不是仅使用相同的流将对象组合在一起 .
我以为Flink做的相当于:
List<Foo> eventsForKey1 = ...;
List<Foo> eventsForKey2 = ...;
List<Foo> eventsForKey3 = ...;
...
List<Foo> eventsForKeyN = ...;
我现在看到Flink实际上做的相当于:
Map<Key, List<Foo>> events = ...;
2 回答
探索各种情况下作业图的外观的最佳方法是编写一些简单的应用程序,并在Flink附带的仪表板中检查其作业图 .
我不确定如何解释你在keyBy之后显示的扇出,这使你难以回答你的问题 . 如果您询问生成的foo DataStream的并行性,它可以是您想要的任何内容 .
如果在keyBy之前和之后并行性为1,那么流将不会像您所示那样被拆分 . 相反,将有一个Window操作符来处理所有键 . (并行性与键的数量无关,但是键控操作符 - 例如滑动窗口及其缩减功能 - 无法利用大于键数的并行度 . )
但即使在单个节点中,您也可以拥有多个内核,并将窗口运算符的并行度设置为3.如果这是您想要的,则后续运算符可以并行处理reduce函数的结果 . 但无论并行性如何,你工作的那部分只有一个DataStream(foo) .
如果我误解了它,请更新你的问题,我会再试一次 .
我认为你真正要问的是你是否在
reduce
操作之后找到KeyedStream
. 如果是这样,那么答案是否定的,你最终定期DataStream
.虽然可以通过
DataStreamUtils.reinterpretAsKeyedStream(DataStream, KeySelector)
将其强制转换回KeyedStream
,但是如果你改变了用于创建窗口密钥的字段值 .