我正在尝试编写一个简单的Kafka Streams应用程序(针对Kafka 2.2 / Confluent 5.2),将具有至少一次语义的输入主题转换为一次精确的输出流。我想对以下逻辑进行编码:
(这肯定会基于我们从上游系统获得的订购保证而提供正确的结果;我在这里不想做任何不可思议的事情。)
起初我以为我可以使用Kafka Streams flatMapValues
operator来做到这一点,它可以让您使用相同的键将每个输入消息映射到零个或多个输出消息。但是,该文档明确警告:
这是一个无记录的逐记录操作(请参阅transformValues(ValueTransformerSupplier,String ...)以进行有状态值转换。
这听起来很有希望,但是transformValues
documentation不清楚如何在每个输入消息中发出零或一个输出消息。除非示例中的// or null
试图这么说?
flatTransform
看上去也很有前途,但是我不需要操纵密钥,并且在可能的情况下,我希望避免重新分区。
有人知道如何正确执行这种过滤吗?
答案 0 :(得分:2)
您可以使用Transformer
来实现如上所述的有状态操作。为了不向下游传播消息,您需要从null
Java文档中提到的transform
方法返回Transformer
。您可以通过processorContext.forward(key, value)
管理传播。下面提供了简化的示例
kStream.transform(() -> new DemoTransformer(stateStoreName), stateStoreName)
public class DemoTransformer implements Transformer<String, String, KeyValue<String, String>> {
private ProcessorContext processorContext;
private String stateStoreName;
private KeyValueStore<String, String> keyValueStore;
public DemoTransformer(String stateStoreName) {
this.stateStoreName = stateStoreName;
}
@Override
public void init(ProcessorContext processorContext) {
this.processorContext = processorContext;
this.keyValueStore = (KeyValueStore) processorContext.getStateStore(stateStoreName);
}
@Override
public KeyValue<String, String> transform(String key, String value) {
String existingValue = keyValueStore.get(key);
if (/* your condition */) {
processorContext.forward(key, value);
keyValueStore.put(key, value);
}
return null;
}
@Override
public void close() {
}
}