Processing time:Stream processing application处理时的时间。Processing time可能落后于Event time几毫秒或者几个小时、几天。如果数据没有被处理,那么就没有Processing time。
Ingestion time:数据存储到Kafka Topic的时间,同样落后于Event time。
Kafka Streams通过TimestampExtractor接口为每个数据记录分配一个时间戳。记录级的时间戳描述了stream的处理进展并被类似于window这样依赖于时间的操作使用。这个时间只在新数据到达后进行更新,称这个由数据驱动的时间为stream time。TimestampExtractor接口的具体实现给stream time提供了不同的语义,比如stream time可以是基于event time的,也可以是基于processing time的。
States如果每一条数据的处理都是相互独立的,没有依赖关系的,那么stream processing不需要状态存储。但是,提供状态存储(state store)能给stream processing提供更多的可能性:比如进行join、group之类的操作。Kafka Streams DSL提供了这些能力。Kafka Streams中每个任务都嵌入了一个或者多个可以通过API访问的状态存储。状态存储可以是持久化的KV或者内存HashMap,也可以是其他的数据结构。Kafka Streams提供了本地state stores的容错和自动恢复。
Kafka Streams架构 Stream Partitions and TasksKafka消息层为了进行存储和传输对数据进行分区;Kafka Streams为了处理数据而分区。在两种场景下,分区保证了数据的可扩展性、容错性、高性能等等。Kafka Streams使用了基于topic partition的partitions和tasks的概念作为并行模型中的逻辑单元。在并发环境行,Kafka Streams和Kafka之间有着紧密的联系:
每个stream partition是顺序的数据记录的集合,并且被映射到一个topic partition
stream中的每个data record对应topic中的一条消息(message)
数据记录中的keys决定了Kafka和Kafka Streams中数据的分区,即,如何将数据路由到指定的分区
应用的processor topology通过拆分成多个task来完成扩容。更具体的,Kafka Streams根据输入的stream partitions创建固定的task,每个task分配来自stream的一个分区列表。分配结果不会变更,所以tasks是应用程序固定的并行单元。Tasks可以根据分配的分区初始化自己的processor topology;它们还可以为每个分配的分区维护一个缓冲,并从这些记录缓冲一次一个地处理消息。作为结果,流任务可以独立和并行的处理而无需手动干预。
理解Kafka Streams不是一个资源管理器是非常重要的,它是一个类库,运行在stream processing application中。多个应用实例可以运行在同一个机器上,也可以运行在多个机器上,Tasks可以自动的分配到运行的实例中。分区和tasks的分配关系不会变更,如果应用实例“挂掉”,实例分配的任务将被自动的在其他的实例上重启并从同样的stream partition开始消费数据。
下图展示了两个task,每个task分配了stream的一个分区的场景:
(图中写入topic C的分区是不是画错了?Task0应该输出topic A p0和topic B p0的数据)
Threading ModelKafka Streams允许用户配置应用实例中类库可以用于并行处理的线程数。每个线程可以执行一个或者多个task。下图中一个线程执行两个stream task:
启动多个stream线程或者实例,仅仅只是增加了topology,使他们并行处理不同的分区。值得注意的是这些线程之间不共享状态,无需协调内部线程。这使得通过多应用实例和线程去并行的运行topology变得非常简单。Kafka topic partition的分配通过Kafka的协调器完成,对Kafka Streams是透明的。
如上所述,Kafka Streams程序的扩容非常简单:仅仅只是多启用一些应用实例,Kafka Streams负责在应用实例中完成分区的task对应的分区的分配。
Local State StoresKafka Streams提供了state stores,可以用于stream processing application存储和查询数据,对于实现有状态的操作非常的重要。Kafka Streams DSL会在使用join()、aggregate()这种有状态的操作时自动的创建和管理state stores。