我的应用程序有一些聚合/窗口操作,所以它有一些存储在其中的状态存储state.dir
.AFAIK,它还将状态存储的更改日志写入代理,那么可以将Kafka Stream应用程序视为无状态POD吗?
我的应用程序有一些聚合/窗口操作,所以它有一些存储在其中的状态存储
state.dir
.AFAIK,它还将状态存储的更改日志写入代理,那么可以将Kafka Stream应用程序视为无状态POD吗?
无状态容量和数据安全性(=无数据丢失):是的,就数据安全而言,您可以将应用程序视为无状态容器; 即无论发生什么事情,Kafka和Kafka Streams保证您不会丢失数据(如果您已经启用了一次性处理,他们也会保证后者).
这是因为,正如您已经说过的,应用程序中的状态更改始终通过相应状态存储的更改日志持续备份到Kafka(代理) - 除非您明确禁用此更改日志功能(默认情况下已启用).
注意:如果您不使用Kafka的Streams默认存储引擎(RocksDB),而是使用备用内存存储引擎,则上述情况甚至是正确的.许多人没有意识到这一点,因为他们阅读"内存中"并且(错误地)得出结论"当机器崩溃,重新启动等时数据将丢失".
无状态pod和应用程序恢复/恢复时间:上面说过,你应该了解pod重启后如何使用本地状态可以影响你的应用程序(或者更确切地说是应用程序实例)的恢复/恢复时间,直到它完全再次运作.
想象一下,有状态应用程序的一个实例在一台机器上运行.它将存储其本地状态state.dir
,并且还将持续备份其本地状态的任何更改到远程Kafka集群(代理).
如果正在重新启动应用程序实例并且无法访问其先前state.dir
(可能是因为它在另一台计算机上重新启动),它将通过从Kafka中的关联更改日志进行恢复来完全重建其状态.根据您的状态大小,这可能需要几毫秒,几秒,几分钟或更长时间.只有在其状态完全恢复后,它才会开始处理新数据.
如果应用程序实例将被重新启动,并有机会获得其先前的state.dir
(可能是因为它是一样的,原来的机器上重新启动),它可以恢复更加迅速,因为它可以重复使用的全部或大部分的当地现有的状态,所以只需要从关联的更改日志中恢复小的增量.只有在其状态完全恢复后,它才会开始处理新数据.
换句话说,如果您的应用程序能够重用现有的本地状态,那么这很好,因为它将最大限度地缩短应用程序恢复时间.
无状态环境中的备用副本:但即使您运行的是无状态容器,也可以通过以下设置将应用程序配置为使用备用副本来最小化应用程序恢复时间num.standby.replicas
:
num.standby.replicas
备用副本的数量.备用副本是本地国家商店的卷影副本.只要有足够的实例运行,Kafka Streams就会尝试创建指定数量的副本并使其保持最新状态.备用副本用于最小化任务故障转移的延迟.先前在故障实例上运行的任务优先在具有备用副本的实例上重新启动,以便可以最小化其更改日志中的本地状态存储恢复过程.
另请参阅文档部分工作负载重新平衡期间的状态恢复
更新2018-08-29:在Kubernetes上运行Kafka/Kafka Streams/KSQL最方便的选择是使用Confluent提供的Confluent Operator或Helm Charts,请参阅https://www.confluent.io/confluent-operator/.(免责声明:我为Confluent工作.)
更新2019-01-10:还有一个Youtube视频,它演示了如何使用Kubernetes扩展Kafka Streams.