我可以在Kafka处理器中拥有本地状态吗?

时间:2018-08-09 14:43:11

标签: java apache-kafka

我一直在阅读有关Kafka并发模型的信息,但是我仍然很难理解我是否可以在Kafka处理器中拥有本地状态,或者这是否会以错误的方式失败?

我的用例是:我有一个更新主题,我想将这些更新插入数据库中,但是我想先对它们进行批处理。我将它们批处理到Processor内的Java ArrayList中,然后发送它们并在标点调用中提交它们。

这会失败吗?我是否保证不会同时访问ArrayList?

我意识到将有多个处理器和多个ArrayList,具体取决于线程和分区的数量,但是我并不在乎。

我还意识到,如果应用程序崩溃,我将丢失ArrayList,但是我不在乎是否将某些事件两次插入数据库。

在我的简单测试中,这很好用,但是对吗?如果没有,为什么?

1 个答案:

答案 0 :(得分:1)

无论您在Kafka消费者应用程序中将其用于本地状态,都由您决定。因此,您可以保证只有当前线程/消费者才能访问阵列列表中的本地状态数据。如果您有多个线程(每个Kafka使用者一个线程),则每个线程可以拥有自己的私有ArrayList或哈希表,以将状态存储到其中。您还可以使用本地RocksDB数据库之类的东西来保持本地状态。

需要注意的几件事:

  • 如果将批处理更新一起发送给数据库,那么这些更新是否以任何方式相关,例如,因为它们是事务的一部分?如果没有,您可能会遇到问题。确保是这种情况的一种简单方法是为带有事务ID或其他一些事务唯一标识符的消息设置密钥,这样所有具有该事务ID的更新都将在一个特定分区中结束,因此食用它们的人一定会始终拥有

    • 在批量更新之前,如何验证已全部交易?同样,如果您要处理事务内部的数据库更新,那么这很重要。您可以简单地等待预定的时间以确保拥有所有更新(例如,对于您的情况,也许30秒就足够了)。或者,您可能会发送“ EndOfTransaction”消息,其中详细说明了应获取的消息数量,以及消息本身的CRC或哈希值。这样,当您收到消息时,可以使用它来验证您是否已拥有所有消息,也可以继续等待尚未收到的消息。

    • 请确保您没有将保存在内存中的消息提交给Kafka,直到 批处理并将它们发送到数据库,并确认更新之后顺利通过。这样,如果您的应用程序死了,则下次重新启动它时,它将再次获得您尚未在Kafka中提交的消息。