Kafka Streams 内部数据管理

Kafka Streams Internal Data Management

在我的公司,我们广泛使用 Kafka,但出于容错原因,我们一直使用关系数据库来存储多个中间转换和聚合的结果。现在我们正在探索 Kafka Streams 作为一种更自然的方式来做到这一点。通常,我们的需求非常简单 - 一个这样的例子是

为了实现这一点,我正在阅读该主题 KTable。代码如下所示

KStreamBuilder builder = new KStreamBuilder();
KTable<String, String> kTable = builder.table("input-topic");
kTable.toStream().foreach((K,V) -> client.post(V));
return builder;

这按预期工作,但我不清楚 Kafka 是如何自动实现这一点的。我假设 Kafka 创建内部主题来实现这一点,但我没有看到创建任何内部主题。 Javadoc for the method seem to confirm this observation. But then I came across this official page 这似乎表明 Kafka 使用一个单独的数据存储,也就是 RocksDB 以及一个更新日志主题。

现在我很困惑,因为更改日志主题是在什么情况下创建的。我的问题是

  1. 如果状态存储的默认行为如官方页面所建议的那样是容错的,那么该状态存储在哪里?在 RocksDB 中?在变更日志主题中或两者?
  2. 在生产中依赖 RocksDB 有什么影响? (已编辑)
    1. 据我了解,对 rocksdb 的依赖是透明的(只是一个 jar 文件),rocksdb 将数据存储在本地文件系统中。但这也意味着在我们的例子中,该应用程序将在应用程序 运行 所在的存储上维护分片数据的副本。当我们用 KTable 替换远程数据库时,它会影响存储,这就是我的观点。
    2. Kafka 版本会确保 RocksDB 继续在各种平台上运行吗? (因为它似乎是平台相关的,而不是写在Java)
  3. 压缩输入主题日志是否有意义?

我正在使用 v.0.11.0

  1. Kafka Streams 在本地存储状态。默认使用 RocksDB。然而,本地状态是短暂的。为了容错,对商店的所有更新也被写入一个变更日志主题。这允许重建 and/or 在发生故障或扩展时迁移存储 in/out。对于您的特殊情况,不会创建更改日志主题,因为 KTable 不是聚合的结果,而是直接从主题填充——这只是一种优化。因为变更日志主题将包含与输入主题完全相同的数据,所以 Kafka Streams 避免了数据重复,并在错误情况下使用输入主题作为变更日志主题。

  2. 不确定你问这个问题的确切含义。请注意,RocksDB 被视为临时存储。出于各种原因默认使用它,如下所述:(例如,它允许保持比主内存更大的状态,因为它可以溢出到磁盘)。您可以将 RocksDB 替换为任何其他存储。 Kafka Streams 还附带了一个内存存储。 (编辑)

    1. 没错。您需要相应地配置您的应用程序,以便能够存储整体状态的本地分片。有一个尺码指南:https://docs.confluent.io/current/streams/sizing.html

    2. RocksDB 是用 C++ 编写的,并通过 JNI 绑定包含在内。 Windows 上存在一些已知问题,因为 RocksDB 并未为 Windows 的所有版本提供预编译的二进制文件。只要您停留在基于 Linux 的平台上,它就应该可以工作。 Kafka 社区为 RocksDB 运行升级测试以确保它的兼容性。

  3. 是的。 Kafka Streams 实际上假定 table() 操作的输入主题是日志压缩的。否则,在发生故障时存在数据丢失的风险。 (编辑)

    1. 如果启用日志压缩,保留时间设置将被忽略。因此,是的,最新更新将永远保持(或直到写入 value=null 的逻辑删除消息)。请注意,当在代理端执行压缩时,旧数据将被垃圾收集,因此在恢复时,每个键只读取新版本——旧版本在压缩过程中被删除。如果一段时间后您对某些数据不感兴趣,则需要将逻辑删除写入源主题以使其正常工作。