我觉得我可能缺少一些基本知识,但我还是会问。
存在具有多个分区的输入主题。我将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存储实例(用于插入或更新)。
答案 0 :(得分:1)
对于process()
,transform()
和transformValues()
,没有自动重新分区。您将需要插入手动through()
调用以重新分区数据。如果将JavaDocs(与支持自动分区的groupBy()
或join()
进行比较),会发现没有为它们提到自动分区。
原因是,这三种方法是Processor API集成到DSL中的一部分,因此没有DSL运营商。它们的语义是未知的,因此我们无法确定密钥是否已更改,是否需要重新分区。为避免不必要的重新分区,将不执行自动重新分区。
还有一个相应的吉拉(Jira):https://issues.apache.org/jira/browse/KAFKA-7608