【问题标题】:Kafka streams exactly once processing use caseKafka 仅在处理用例时流式传输
【发布时间】:2019-01-10 04:25:42
【问题描述】:
我有一个用例,我需要从主题读取数据,然后是批处理数据(100 条记录)并将批处理写入特定文件或外部存储。我计划为此使用处理器 API,并使用由 kafka 支持的状态存储对处理中的数据进行批处理,并在批处理大小达到 100 条记录后写入文件。从状态存储中清除批次以创建新的批次。
还有一个要求是我们不能有重复的数据。这意味着相同的记录不能在两个不同的批次中。
流是否恰好适合此用例?我在设计中读到,如果我们对数据进行批处理,则不建议这样做,并且大多数关于此的文章都说 Exactly once 仅在消耗过程和生产模式的情况下有效。
【问题讨论】:
标签:
apache-kafka
apache-kafka-streams
【解决方案1】:
Kafka Stream 仅在将结果写回 Kafka 时才有效。因为要向外部系统写入数据,所以 Kafka 无法为Exactly-once 保证提供任何帮助,因为Kafka 事务不是跨系统事务。
【解决方案2】:
正如@Matthias 所指出的,只有一种语义只适用于 Kafka 流到 Kafka 流类型的应用程序,与外部系统的集成可能会破坏语义。您可以在this 文章中了解更多信息。
我建议您使用 Kafka Consumer API,因为它将为您的用例提供灵活性和抽象之间的最佳平衡。您需要做的就是删除 enable.auto.commit=false 并在使用 consumer.commitSync() 成功将批处理写入外部系统后手动提交;
根据您的用例,有时确保只执行一次可能会有些困难。您需要使用自定义逻辑确保您的消费者是幂等的。您可以考虑使用外部持久存储来保持消息的散列(或密钥,如果它是唯一的),并检查每条消息是否尚未处理。您也可以为此目的使用状态存储,但我觉得清除状态存储有时会很麻烦,但这在很大程度上取决于您的用例。
如果有帮助,您可以查看this 文章。