使用selectKey和transform在DSL拓扑上对流进行重新分区

时间:2019-02-13 23:03:10

标签: apache-kafka apache-kafka-streams

我觉得我可能缺少一些基本知识,但我还是会问。

存在具有多个分区的输入主题。我将selectKey用作DSL拓扑的一部分。 selectKey始终返回相同的值。我的期望是,在由selectKey()触发内部重新分区之后,拓扑中的下一个处理器将在同一分区的同一键上被调用。但是,在同一键的不同分区上将调用下一个为transform()的处理器。

拓扑:

    Topology buildTopology() {
        final StreamsBuilder builder = new StreamsBuilder();


        builder
            .stream("in-topic", Consumed.with(Serdes.String(), new JsonSerde<>(CatalogEvent.class)))
            .selectKey((k,v) -> "key")
            .transform(() -> new Processor())
            .print();

        return builder.build();
    }

transform使用的处理器类

public class Processor implements Transformer<String, CatalogEvent, KeyValue<String, DispEvent>> {

    private ProcessorContext context;

    @Override
    public void init(ProcessorContext context) {
        this.context = context;
    }

    @Override
    public KeyValue<String, DispEvent> transform(String key, CatalogEvent catalogEvent) {
        System.out.println("key:" + key + " partition:" + context.partition());
        return null;
    }

    @Override
    public KeyValue<String, DispatcherEvent> punctuate(long timestamp) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void close() {
        // TODO Auto-generated method stub

    }
}

“主题内”有两个带有随机UUID作为密钥的消息,即“ 8f45e552-8886-4781-bb0c-79ca98f9d927”,“ a794ed2a-6f7d-4522-a7ac-27c51a64fa28”,两个消息的有效载荷均相同< / p>

来自Processor :: transform的两个UUID的输出是

key:key partition: 2
key:key partition: 0

如何更改拓扑以确保具有相同密钥的消息将到达相同的分区-我需要它以确保具有相同密钥的消息将到达相同的本地Kafka存储实例(用于插入或更新)。

1 个答案:

答案 0 :(得分:1)

对于process()transform()transformValues(),没有自动重新分区。您将需要插入手动through()调用以重新分区数据。如果将JavaDocs(与支持自动分区的groupBy()join()进行比较),会发现没有为它们提到自动分区。

原因是,这三种方法是Processor API集成到DSL中的一部分,因此没有DSL运营商。它们的语义是未知的,因此我们无法确定密钥是否已更改,是否需要重新分区。为避免不必要的重新分区,将不执行自动重新分区。

还有一个相应的吉拉(Jira):https://issues.apache.org/jira/browse/KAFKA-7608