Tombstone消息没有从KTable状态商店删除记录?

时间:2018-06-05 20:14:37

标签: apache-kafka-streams spring-cloud-stream spring-kafka

我正在从KStream创建KTable处理数据。但是当我使用key和null有效负载触发逻辑删除消息时,它不会从KTable中删除消息。

样本 -

public KStream<String, GenericRecord> processRecord(@Input(Channel.TEST) KStream<GenericRecord, GenericRecord> testStream,
KTable<String, GenericRecord> table = testStream
                .map((genericRecord, genericRecord2) -> KeyValue.pair(genericRecord.get("field1") + "", genericRecord2))
                .groupByKey()
                reduce((genericRecord, v1) -> v1, Materialized.as("test-store"));


GenericRecord genericRecord = new GenericData.Record(getAvroSchema(keySchema));
genericRecord.put("field1", Long.parseLong(test.getField1()));
ProducerRecord record = new ProducerRecord(Channel.TEST, genericRecord, null);
kafkaTemplate.send(record);

在触发具有空值的消息时,我可以使用null有效负载调试testStream map函数,但它不会删除KTable更改日志&#34; test-store&#34;上的记录。看起来它甚至没有达到减少方法,不知道我在这里缺少什么。

感谢您的任何帮助!

感谢。

2 个答案:

答案 0 :(得分:5)

reduce()

的JavaDocs中所述
  

忽略{@code null}键或值的记录。

因为,<key,null>记录被删除,因此永远不会执行(genericRecord, v1) -> v1,所以不会将任何逻辑删除写入商店或更改日志主题。

对于您想到的用例,您需要使用表示“删除”的代理值,例如Avro记录中的布尔标志。您的reduce函数需要检查标志,如果设置了标志,则返回null;否则,它必须定期处理记录。

答案 1 :(得分:0)

Matthias对上述答案的补充:

Reduce忽略流中的第一条记录,因此映射和分组的值将按原样存储在KTable中,而不用通过reduce方法进行逻辑删除。这意味着不可能仅在该表上加入另一个流,还需要对值本身进行求值。

我希望KIP-523能解决这个问题。