如何将KStream聚合到固定大小的列表?

时间:2016-12-02 10:43:03

标签: java apache-kafka apache-kafka-streams

同样但问题略有不同:KStream batch process windows,我想在将消息推送到消费者之前批量处理来自KStream的消息。

但是,不应在固定的时间窗口上安排此下推,而是在每个密钥的固定消息计数阈值上安排。

对于初学者来说,我会想到两个问题:

1)自定义AbstractProcessor应该如何处理?有点像:

@Override
public void punctuate(long streamTime) {
    KeyValueIterator<String, Message[]> it = messageStore.all();
    while (it.hasNext()) 
        KeyValue<String, Message[]> entry = it.next();
        if (entry.value.length > 10) {
            this.context.forward(entry.key, entry.value);
            entry.value = new Message[10]();
        }
    }
}

2)由于StateStore可能会爆炸(如果条目值永远不会达到阈值以便转发),那么“垃圾收集”的最佳方法是什么?这个?我可以做一个基于时间的计划并删除太旧的键......但这看起来很DIY并且容易出错。

1 个答案:

答案 0 :(得分:2)

我想这会奏效。应用基于时间的“垃圾收集”听起来也很合理。是的,使用Processor API代替DSL有一些DIY的味道 - 首先不是PAPI的目的(使用户能够做任何需要的事情)。

虽然有一些评论:

  • 您将需要更复杂的数据结构:因为punctuate()是基于流时间进度调用的,所以您可能会在两次调用之间为一个键创建超过10条记录。因此,您需要KeyValueIterator<String, List<Message[]>> it = messageStore.all();之类的内容才能为每个密钥存储多个批次。
  • 我认为你需要微调标点的时间表,这将是棘手的 - 如果你的日程安排太紧,许多批次可能还没有完成而你浪费CPU - 如果你的日程太松,你将需要大量的内存,而你的下游操作员会在你一次发出大量内容时获得大量数据。向下游发送数据突发可能会成为一个问题。
  • 扫描整个商店的费用很高 - 尝试根据批量大小对“键值对”进行“排序”似乎是个好主意。这应该使您只能触摸已完成批次的键而不是所有键。也许你可以保留一个内存列表中的密钥,这些密钥已经完成批处理并且只对这些密钥进行查找(失败时,你需要对来自商店的所有密钥进行单次传递以重新创建这个内存列表)。