Java 添加全局存储的Kafka streams用例
在kafka streams中定义拓扑时,可以添加全局状态存储。它将需要一个源主题以及一个Java 添加全局存储的Kafka streams用例,java,apache-kafka,apache-kafka-streams,Java,Apache Kafka,Apache Kafka Streams,在kafka streams中定义拓扑时,可以添加全局状态存储。它将需要一个源主题以及一个处理器供应商。 处理器接收记录,并可以在理论上对其进行转换,然后再将其添加到存储中。但是在恢复的情况下,记录直接从源主题(changelog)插入到全局状态存储中,跳过处理器中完成的最终转换 +-------------+ +-------------+ +---------------+ | |
处理器供应商
。
处理器接收记录,并可以在理论上对其进行转换,然后再将其添加到存储中。但是在恢复的情况下,记录直接从源主题(changelog)插入到全局状态存储中,跳过处理器中完成的最终转换
+-------------+ +-------------+ +---------------+
| | | | | global |
|source topic -------------> processor +--------------> state |
|(changelog) | | | | store |
+-------------+ +-------------+ +---------------+
| ^
| |
+---------------------------------------------------------+
record directly inserted during restoration
将全局状态存储添加到拓扑中
根据文件
注意:不应使用处理器将转换后的记录插入全局状态存储中。此存储将源主题用作changelog,并且在还原期间将直接从源插入记录。此ProcessorNode应用于保持StateStore为最新状态
同时,kafka bug tracker上的主要bug目前是开放的:它准确地解释了文档中所述的内容,但似乎是一个公认的bug
我想知道卡夫卡7663是否真的是一个bug。根据文档,它似乎是这样设计的,在这种情况下,我很难理解用例。有人能解释一下这个低级API的主要用例吗?我唯一能想到的就是处理副作用,例如,在处理器中执行一些日志操作
+-------------+ +-------------+ +---------------+
| | | | | global |
|source topic -------------> processor +--------------> state |
|(changelog) | | | | store |
+-------------+ +-------------+ +---------------+
| ^
| |
+---------------------------------------------------------+
record directly inserted during restoration
附加问题:如果源主题充当全局存储的变更日志,当由于保留期已过期而从主题中删除记录时,是否将其从全局状态存储中删除?或者只有在从changelog进行完整的存储恢复后,才会在存储中进行删除。是的,这是一个非常奇怪的第22条军规,但文档是正确的。全局状态存储的处理器不能对记录执行任何操作,而是将它们持久化到存储中 好了,这不是一个哲学问题,只是一个实践问题。原因很简单,就是你观察到的行为。。。Streams将输入主题视为存储的changelog主题,因此在恢复期间绕过处理器(以及反序列化) 状态恢复绕过任何处理的原因是,变更日志中的数据通常与存储中的数据相同,因此对其执行任何新操作实际上都是错误的。另外,只需将字节从线路上取下,并将它们批量写入状态存储中,效率更高。我之所以说“通常”,是因为在这种情况下,输入主题与普通的changelog主题并不完全相同,因为它在存储放置期间不接收写入 对于它的价值,我也很难理解用例。看起来,我们应该:
- 继续使用输入主题,并在恢复期间反序列化和调用处理器,或者
- 为全局存储添加一个真正的变更日志,这样我们就可以轮询输入主题,应用一些转换,然后写入全局存储和全局存储变更日志。然后,我们可以使用变更日志(而不是输入)进行恢复和复制
to(my global changelog)
来制作一个“changelog”主题,立即对其进行近似处理。然后,您将创建全局存储来读取my global changelog
,而不是输入
所以,给你一个直接的答案,卡夫卡-7663不是一个bug。我将对提议将其转换为功能请求的票证进行评论
额外的回答:充当状态存储更改日志的主题不能配置保留。实际上,这意味着您应该通过启用压缩来防止无限增长,并禁用日志保留
实际上,旧数据从保留中丢失并被删除并不是一个“事件”,消费者无法知道它是否/何时发生。因此,无法从状态存储中删除数据以响应此非事件。正如你所描述的那样。。。这些记录将无限期地保存在全球存储中。如果/当一个实例被替换时,新实例将从输入中恢复,并且(显然)只接收当时主题中存在的记录。因此,Streams集群作为一个整体将以一个不一致的全局状态视图结束。这就是为什么您应该禁用保留
从存储中“删除”旧数据的正确方法是将所需键的墓碑写入输入主题。然后,这将正确传播到集群的所有成员,在恢复期间正确应用,并由代理正确压缩
我希望这一切都有帮助。当然,请在门票上插话,帮助我们塑造更直观的API 目前似乎没有一种方法可以监听KGlobalTable上的更改 使用全局存储和自定义处理器可以获得类似的结果
+-------------+ +-------------+ +---------------+
| | | | | global |
|source topic -------------> processor +--------------> state |
|(changelog) | | | | store |
+-------------+ +-------------+ +---------------+
| ^
| |
+---------------------------------------------------------+
record directly inserted during restoration
我在这里偶然发现了这个
我并不是说这是一个好的用例,但作为一种解决方法,它可能会有所帮助。请注意,以前的文档并没有指出这个问题,我们只是将文档更新为“中间修复”。是的,它确实帮助很大。感谢您的详细回答:)澄清“充当状态存储的更改日志的主题不得配置保留。”:这意味着您不应将主题配置为在经过特定时间或超过特定大小阈值后使数据过期。相反,数据应该“永远”保留在主题中,启用压缩有助于确保主题仍然不会超出范围