我正在使用apacheflink实现一个实时流etl管道。管道具有以下特点:
摄取单个运动流: stream-A
流具有类型为的记录 EventA
它们有一个 category_id
,表示不同的逻辑流
由于这些逻辑流是如何写入kinesis的(每个category\u id有一个单独的生产者,以串行方式写入),因此这些逻辑流保证按顺序读取 FlinkKinesisConsumer
flink执行一些顺序处理工作,由category\u id设置关键字,生成一个 EventB
数据记录
这些记录都是写给凯西斯的 stream-B
一个单独的服务从 stream-B
这是很重要的,这发生的顺序。
处理过程如下所示:
val in_events = env.addSource(new FlinkKinesisConsumer[EventA]( # these are guaranteed ordered
"stream-A",
new EventASchema,
consumerConfig))
val out_events = in_events
.keyBy(event => event.category_id)
.process(new EventAStreamProcessor)
out_events.addSink(new FlinkKinesisProducer[EventB](
"stream-B",
new EventBSchema,
producerConfig))
# a separate service reads the out_events and wants them in-order
根据这里的指导方针,似乎不可能保证 EventB
写在Flume里的记录。我只在乎那些和我一样的事情 category_id
是按顺序写的,因为下游服务将按此键控。从第一个原则出发,如果我手动实现线程,我会为每个线程设置一个单独的队列 category_id
keyedstream并确保它们是串行写入kinesis的(这看起来像是对默认情况下所做工作的严格概括,即使用具有单个全局队列的threadpool)。是吗 FlinkKinesisProducer
支持这个机制还是有办法绕过这个限制使用Flink的 keyBy
或者类似的构造?每个独立Flume category_id
也许 吧?对于最后一个选项,我预计10万 category_id
所以这可能有太多的内存开销。
一种选择是缓冲从中读取的事件 stream-B
在下游服务中对它们进行排序(如果缓冲区窗口较大,则很有可能)。这在理论上应该是可行的,但它使下游服务比它需要的更复杂,排除了确定性,因为它依赖于网络调用的随机定时,而且更重要的是,增加了管道的延迟(尽管总体上可能比强制串行写入流-b的延迟要小?)。所以理想的情况下,我希望有另一个选择。而且,这感觉像是一个常见的问题,所以也许有更聪明的解决方案,或者我错过了一些明显的东西
非常感谢。
暂无答案!
目前还没有任何答案,快来回答吧!