我们有以下用例:
从主题读取(预期吞吐量是每2秒记录一个密钥),groupByKey,并在30分钟的窗口内进行窗口聚合,并以1分钟的跳跃时间进行。 聚合只是附加接收到的记录。
应用程序启动时,一切正常,但在后期阶段,聚合大小增加时,应用程序变慢和滞后
拓扑:
KStream<String, Foo> numericStream = builder.stream("topic", Consumed.with(Serdes.String(), FooSerde));
static Duration WINDOW_MS = Duration.ofMinutes(30);
static Duration ADVANCE_MS = Duration.ofMinutes(15);
KStream<Windowed<String>, Foo1> windowedStream = numericStream.peek((key, value) -> System.out.println(value.getDateTime()))
.groupByKey()
.windowedBy((TimeWindows.of(WINDOW_MS).advanceBy(ADVANCE_MS)).grace(Duration.ofMillis(30)))
.aggregate(new Initializer<Foo1>() {
@Override
public Foo1 apply() {
return new Foo1();
}},
(key, value, aggregate) -> {
aggregate.append(value);
return aggregate;
},
Materialized.<String, Foo1, WindowStore<Bytes,byte[]>>as("some_name").withValueSerde(Foo1Serde))
.toStream()
.peek((key, value) -> System.out.println(" Key: "+key+ " Start: "+getISTTime(key.window().start()) + " End: "+ getISTTime(key.window().end()) +" Count: " + value.getCount() ));
每个记录的大小约为20KB。当聚合大小超过10MB左右并因此出现滞后时,记录的处理时间将超过2秒。
将COMMIT_INTERVAL_MS_CONFIG设置为0,因为状态存储应该始终是最新的,具有最新的数据包,并且查询状态存储,并且间隔不同。
我们如何消除应用程序的滞后,这与RocksDB I / O操作有关吗?因为计数操作而不是合计没有任何滞后
每个主题有3个分区,但是具有相同键的记录进入同一分区,那么线程/多个实例会有所帮助吗?
我们也正在考虑在不使用窗口的情况下进行此操作,窗口是否会为较大的聚合创建此类滞后?
答案 0 :(得分:2)
由于您在RocksDB中读写越来越大的数据,因此可能会减慢处理速度。
是的,在这种情况下,在一个实例中使用三个线程或以一个线程启动三个实例可能也有帮助。使用拓扑和三个分区,处理将分布在三个任务上。如果只有一个带一个线程的实例,则所有三个任务将由同一线程运行。您可以通过使用三个线程指定一个实例来进行扩展,也可以通过在不同的计算节点上分别使用一个线程来启动三个实例来进行扩展。在两个实例之间进行设置,一个实例有两个线程,另一个实例有一个线程也可以。
没有窗口,聚合将永远不会过期,也不会从状态存储中删除。因此,状态存储中的数据将无限期增长,并且可能会减慢状态存储的速度。
如果使用交互式查询来查询状态存储,则无需将COMMIT_INTERVAL_MS_CONFIG设置为0,因为交互式查询还会查询状态存储前面的缓存。实际上,将COMMIT_INTERVAL_MS_CONFIG设置为零也可能会减慢您的处理速度,因为您不断将数据写入磁盘会增加磁盘I / O。