首页 > 解决方案 > Kafka Streams 内部数据管理

问题描述

在我的公司,我们广泛使用 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似乎证实了这一观察。但后来我遇到了这个官方页面,它似乎暗示 Kafka 使用了一个单独的数据存储,即 RocksDB 以及一个变更日志主题。

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

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

我正在使用 v. 0.11.0

标签: apache-kafkaapache-kafka-streams

解决方案


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

  2. 不知道你这个问题到底是什么意思。请注意,RocksDB 被视为临时存储。出于各种原因默认使用它,如下所述:为什么 Apache Kafka Streams 使用 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. 如果启用日志压缩,则保留时间设置将被忽略。因此,是的,最新的更新将永远保持(或直到null写入带有 value= 的墓碑消息)。请注意,当在代理端执行压缩时,旧数据被垃圾收集,因此,在恢复时,每个键只读取新版本——在压缩过程中旧版本被删除。如果一段时间后您对某些数据不感兴趣,则需要在源主题中写入墓碑以使其工作。

推荐阅读