我们使用处理器API构建了Kafka Streams Java拓扑。
在拓扑结构中,我们有一个处理器,它可以保存到多个状态存储中。
当我们使用at_least_once时,我们会看到状态存储之间的一些不一致——例如,传入的记录会导致同时写入状态存储A和B,但存储之间的崩溃只会导致保存到存储A被写入Kafka更改日志主题。
-
我们是否保证保存的顺序也将是写入状态存储的顺序?例如,如果我们先保存到存储A,然后保存到存储B,我们当然可能会出现对两个更改日志的写入都成功的情况,以及只完成对更改日志A的写入的情况,但我们是否也会出现只完成了对更改日志B的写入的情况?
-
什么情况会导致重播?当然是崩溃,但重新平衡、新的broker分区领导者,或者当我们收到"偏移提交失败"错误(请求超时)时,该怎么办?
-
不久前,我们尝试使用exactly_once,这导致了很多错误消息,这对我们来说没有意义。exactly_once会在多个状态存储中为我们提供原子写入吗?
Ad 3。根据Kafka Streams中一次支持的原始设计文档,我认为使用eaxctly_once
可以在多个状态存储中进行原子写入
当调用stream.commit()时,将按顺序执行以下步骤:
- 刷新本地状态存储(KTable缓存)以确保所有变更日志记录都发送到下游
- 调用producer.sendOffsetsToTransactions(offset)以提交当前记录的消费者在事务中的位置。请注意,尽管线程的使用者可以在多个任务之间共享,因此也可以由多个生产者共享,但任务分配的分区始终是独占的,因此,只提交此任务分配分区的偏移量是安全的
- 调用producer.commitTransaction()以提交当前事务。结果,以上述三元组表示的任务状态被原子地提交
- 再次调用generator.beginTransaction()以启动下一个事务