我正在使用Kafka Streams版本0.10.0.1,并尝试在流中查找最小值。
传入的消息来自一个名为kafka-streams-topic的主题,并且有一个密钥,值是一个JSON有效负载,如下所示:
{"value":2334}
这是一个简单的有效负载,但我想找到这个JSON的最小值。
传出消息只是一个数字: 2334
,密钥也是信息的一部分。
因此,如果传入的主题得到:
key=1, value={"value":1000}
传出的主题,名为min-topic,将获得
key=1,value=1000
另一条消息传来:
key=1, value={"value":100}
因为这是我想要生成一条key = 1 value = 100的消息的相同密钥,因为它现在小于第一条消息
现在让我们说:
key=2 value=99
将在以下位置生成新消息:
key=2 and value=99 but the key=1 and associated value shouldn't change.
此外,如果我们收到消息:
key=1 value=2000
由于此消息大于当前值100
,因此不应生成任何消息这有效,但我想知道这是否符合API的意图:
public class MinProcessor implements Processor<String,String> {
private ProcessorContext context;
private KeyValueStore<String, Long> kvStore;
private Gson gson = new Gson();
@Override
public void init(ProcessorContext context) {
this.context = context;
this.context.schedule(1000);
kvStore = (KeyValueStore) context.getStateStore("Counts");
}
@Override
public void process(String key, String value) {
Long incomingPotentialMin = ((Double)gson.fromJson(value, Map.class).get("value")).longValue();
Long minForKey = kvStore.get(key);
System.out.printf("key: %s incomingPotentialMin: %s minForKey: %s \n", key, incomingPotentialMin, minForKey);
if (minForKey == null || incomingPotentialMin < minForKey) {
kvStore.put(key, incomingPotentialMin);
context.forward(key, incomingPotentialMin.toString());
context.commit();
}
}
@Override
public void punctuate(long timestamp) {}
@Override
public void close() {
kvStore.close();
}
}
以下是实际运行处理器的代码:
public class MinLauncher {
public static void main(String[] args) {
TopologyBuilder builder = new TopologyBuilder();
StateStoreSupplier countStore = Stores.create("Counts")
.withKeys(Serdes.String())
.withValues(Serdes.Long())
.persistent()
.build();
builder.addSource("source", "kafka-streams-topic")
.addProcessor("process", () -> new MinProcessor(), "source")
.addStateStore(countStore, "process")
.addSink("sink", "min-topic", "process");
KafkaStreams streams = new KafkaStreams(builder, KafkaStreamsProperties.properties("kafka-streams-min-poc"));
streams.cleanUp();
streams.start();
Runtime.getRuntime().addShutdownHook(new Thread(streams::close));
}
}
答案 0 :(得分:2)
不确定您的确切输入数据和结果是什么(也许您可以使用以下信息更新您的问题:您的输入记录是什么?您的输出是什么?“EXTRA messages []产生了什么[] [你不要指望“?)。
然而,一些一般性的澄清(如果需要,可以稍后改进这个答案)。
punctuate()
中发出定期调用的数据(基于内部跟踪的流时间 - 即,基于通过TimestampExtractor
从输入记录中提取的时间戳值)。因此,当punctuate()
被调用时,您将写入写入主题的每个键的 当前 最小值,因此,每个键可以有多个更新全部附加到您的结果主题。 (主题仅附加,如果您使用相同的密钥编写两条消息,则会看到两者 - 没有覆盖。)