Apache kafka 卡夫卡州立商店的最新状态是什么?

Apache kafka 卡夫卡州立商店的最新状态是什么?,apache-kafka,apache-kafka-streams,kafka-interactive-queries,Apache Kafka,Apache Kafka Streams,Kafka Interactive Queries,我正在试图理解KTables应该是什么状态 我在看书,上面写着 此存储将保留在上找到的任何单词的最新计数 主题“字数输入” 假设一条消息成功发送到主题T 这是否意味着在一个由T构建的表上的所有交互式查询都能保证立即看到更改?(作为builder.table(“T”,…)构建) 这是否意味着从T聚合的表上的所有交互式查询都能保证立即看到更改?(编译为builder.stream(“T”).groupByKey().aggregate(…) 上面说: KTable查找始终在KTable的当前状态下进

我正在试图理解KTables应该是什么状态

我在看书,上面写着

此存储将保留在上找到的任何单词的最新计数 主题“字数输入”

假设一条消息成功发送到主题T

  • 这是否意味着在一个由T构建的表上的所有交互式查询都能保证立即看到更改?(作为builder.table(“T”,…)构建)
  • 这是否意味着从T聚合的表上的所有交互式查询都能保证立即看到更改?(编译为builder.stream(“T”).groupByKey().aggregate(…)
  • 上面说:

    KTable查找始终在KTable的当前状态下进行; 因此,无序记录可能会产生不确定的结果

    鉴于:

    • 流S1作为构建器构建。流(“T”)
    • 表T1构建为S1.groupByKey().aggregate(…)
    • 流S2由S1与T1连接
    三,。是否保证联接操作总是在聚合之后发生,因此每个新记录总是先聚合然后联接,而不是相反

    添加了


    我这里的主要问题是什么时候可以通过交互式查询或联接请求数据。是否有可能获取过时数据/是否有可能出现延迟?

    如果消息成功发送到主题T

  • 是的,状态存储总是使用给定密钥的最新值进行更新。只要
    builder.table(“T”,…)
    接收到现有键的新更新,交互式查询将返回一个新值

  • 是的,所有以某种方式链接到主题T的状态存储都将基于新的更新进行更新
    builder.stream(“T”).groupByKey().aggregate(…)
    还将更新下面的状态存储

  • 对于
    S1=builder.stream(“T”),T1=S1.groupByKey().aggregate(…),S2=S1.join(T1)
    ,它遵循流表连接语义。KTable上的更新将始终更新内部右侧连接状态,但仅当流中有一些新记录时(左侧)才会触发连接操作

  • 下面是KStream KTable连接语义的一个很好的示例:

    经过一些调试,找到了第三部分的答案:

  • 对于输入主题中的每条新消息,该消息将按照创建拓扑时使用的顺序遍历整个拓扑,然后在单个事务中提交所有更改。这就是为什么消息总是先在ktable中持久化,然后才加入消息。因此,在我用来测试延迟的版本中,延迟是不可能的,因为它是一个线程和一个事务,并且顺序是定义的
  • 以下是一个例子:

    测试等级:

    package myapps;
    
    import org.apache.kafka.clients.producer.ProducerRecord;
    import org.apache.kafka.common.serialization.LongSerializer;
    import org.apache.kafka.common.serialization.Serdes;
    import org.apache.kafka.common.serialization.StringDeserializer;
    import org.apache.kafka.common.serialization.StringSerializer;
    import org.apache.kafka.streams.StreamsBuilder;
    import org.apache.kafka.streams.StreamsConfig;
    import org.apache.kafka.streams.Topology;
    import org.apache.kafka.streams.TopologyTestDriver;
    import org.apache.kafka.streams.kstream.KStream;
    import org.apache.kafka.streams.kstream.KTable;
    import org.apache.kafka.streams.kstream.Materialized;
    import org.apache.kafka.streams.kstream.Produced;
    import org.apache.kafka.streams.test.ConsumerRecordFactory;
    import org.junit.Assert;
    import org.junit.Test;
    
    import java.util.Properties;
    
    public class TopologyTest {
    
        private static final String INPUT_TOPIC = "input-topic";
        private static final String OUTPUT_TOPIC = "output-topic";
    
        @Test
        public void testStreams() {
    
            Topology topology = createTopology();
    
            Properties config = new Properties();
            config.put(StreamsConfig.APPLICATION_ID_CONFIG, "test");
            config.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "dummy:1234");
            config.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());
            config.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.Long().getClass().getName());
    
            try (TopologyTestDriver testDriver = new TopologyTestDriver(topology, config)) {
    
                ConsumerRecordFactory<String, Long> factory = new ConsumerRecordFactory<>(
                        INPUT_TOPIC, new StringSerializer(), new LongSerializer());
    
                testDriver.pipeInput(factory.create(INPUT_TOPIC, "key", 1L));
                testDriver.pipeInput(factory.create(INPUT_TOPIC, "key", 2L));
                testDriver.pipeInput(factory.create(INPUT_TOPIC, "key", 3L));
    
                ProducerRecord<String, String> pr1 = testDriver.readOutput(OUTPUT_TOPIC, new StringDeserializer(), new StringDeserializer());
                ProducerRecord<String, String> pr2 = testDriver.readOutput(OUTPUT_TOPIC, new StringDeserializer(), new StringDeserializer());
                ProducerRecord<String, String> pr3 = testDriver.readOutput(OUTPUT_TOPIC, new StringDeserializer(), new StringDeserializer());
    
                Assert.assertEquals("1,1", pr1.value());
                Assert.assertEquals("2,3", pr2.value());
                Assert.assertEquals("3,6", pr3.value());
            }
        }
    
        private Topology createTopology() {
            StreamsBuilder builder = new StreamsBuilder();
            KStream<String, Long> inputStream = builder.stream(INPUT_TOPIC);
    
            KTable<String, Long> table = inputStream.groupByKey().aggregate(
                    () -> 0L,
                    (key, value, aggregate) -> value + aggregate,
                    Materialized.as("store")
            );
    
            KStream<String, String> joined = inputStream
                    .join(table, (value, aggregate) -> value + "," + aggregate);
    
            joined.to(OUTPUT_TOPIC, Produced.with(Serdes.String(), Serdes.String()));
    
            return builder.build();
        }
    
    }
    
    打包myapps;
    导入org.apache.kafka.clients.producer.ProducerRecord;
    导入org.apache.kafka.common.serialization.lonserializer;
    导入org.apache.kafka.common.serialization.Serdes;
    导入org.apache.kafka.common.serialization.StringDeserializer;
    导入org.apache.kafka.common.serialization.StringSerializer;
    导入org.apache.kafka.streams.StreamsBuilder;
    导入org.apache.kafka.streams.StreamsConfig;
    导入org.apache.kafka.streams.Topology;
    导入org.apache.kafka.streams.TopologyTestDriver;
    导入org.apache.kafka.streams.kstream.kstream;
    导入org.apache.kafka.streams.kstream.KTable;
    导入org.apache.kafka.streams.kstream.Materialized;
    导入org.apache.kafka.streams.kstream.producted;
    导入org.apache.kafka.streams.test.ConsumerRecordFactory;
    导入org.junit.Assert;
    导入org.junit.Test;
    导入java.util.Properties;
    公共类地形测试{
    私有静态最终字符串输入\u TOPIC=“输入主题”;
    私有静态最终字符串输出\u TOPIC=“OUTPUT TOPIC”;
    @试验
    公共void testStreams(){
    拓扑=createTopology();
    属性配置=新属性();
    config.put(StreamsConfig.APPLICATION_ID_config,“test”);
    config.put(StreamsConfig.BOOTSTRAP_SERVERS_config,“dummy:1234”);
    config.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_config,Serdes.String().getClass().getName());
    config.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_config,Serdes.Long().getClass().getName());
    try(TopologyTestDriver testDriver=新的TopologyTestDriver(拓扑,配置)){
    ConsumerRecordFactory工厂=新的ConsumerRecordFactory工厂(
    输入_主题,新建StringSerializer(),新建LongSerializer());
    testDriver.pipeInput(factory.create(输入主题“key”,1L));
    testDriver.pipeInput(factory.create(输入主题“key”,2L));
    testDriver.pipeInput(factory.create(输入主题“key”,3L));
    ProducerRecord pr1=testDriver.readOutput(输出主题,new StringDeserializer(),new StringDeserializer());
    ProducerRecord pr2=testDriver.readOutput(输出主题,new StringDeserializer(),new StringDeserializer());
    ProducerRecord pr3=testDriver.readOutput(输出主题,new StringDeserializer(),new StringDeserializer());
    Assert.assertEquals(“1,1”,pr1.value());
    Assert.assertEquals(“2,3”,pr2.value());
    Assert.assertEquals(“3,6”,pr3.value());
    }
    }
    私有拓扑createTopology(){
    StreamsBuilder builder=新的StreamsBuilder();
    KStream inputStream=builder.stream(输入主题);
    KTable table=inputStream.groupByKey().aggregate(
    ()->0升,
    (键、值、聚合)->值+聚合,
    物化。作为(“存储”)
    );
    KStream=inputStream
    .join(表(值,聚合)->value+“,”+聚合);
    joined.to(输出主题,生成的.with(Serdes.String(),Serdes.String());
    返回builder.build();
    
    <dependencies>
        <!-- Apache Kafka dependencies -->
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-streams</artifactId>
            <version>2.3.0</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-streams-test-utils</artifactId>
            <version>2.3.0</version>
            <scope>test</scope>
        </dependency>
    
    </dependencies>