KStreams-如何处理有关一个主题的消息延迟

时间:2020-01-06 14:43:26

标签: apache-kafka apache-kafka-streams

我有一个基于Spring Boot的KStreams应用程序,在其中我要跨多个主题联接数据。当某个主题出现延迟时,什么是/最好的处理情况?我已经阅读了How to manage Kafka KStream to Kstream windowed join?等链接。

这是我的示例代码(Spring Boot App),用于生成针对2个主题的模拟数据-员工和财务。以下员工主题代码:

private void sendEmpData() {
    IntStream.range(0, 1).forEach(index -> {
        EmployeeKey key = new EmployeeKey();
        key.setEmployeeId(1);

        Employee employee = new Employee();
        employee.setDepartmentId(1000);
        employee.setEmployeeFirstName("John);
        employee.setEmployeeId(1);
        employee.setEmployeeLastName("Doe");

        kafkaTemplateForEmp.send(EMP_TOPIC, key, employee);
    });
}

与金融主题类似:

private void sendFinanceData() {
    IntStream.range(0, 1).forEach(index -> {
        FinanceKey key = new FinanceKey();
        key.setEmployeeId(1);
        key.setDepartmentId(1000);

        Finance finance = new Finance();
        finance.setDepartmentId(1000);
        finance.setEmployeeId(1);
        finance.setSalary(2000);

        kafkaTemplateForFinance.send(FINANCE_TOPIC, key, finance);
    });
}

与这些记录关联的时间戳类型是 TimeStampType.CREATE_TIME ,我假设它与 事件时间 < / strong>在流中。

我有一个简单的KStreams应用程序,它为财务主题重新设置了密钥,以使财务流密钥与员工流密钥匹配,然后按如下所示进行联接:

employeeKStream.join(reKeyedStream,
            (employee, finance) -> new EmployeeFinance(employee.getEmployeeId(),
                    employee.getEmployeeFirstName(),
                    employee.getEmployeeLastName(),
                    employee.getDepartmentId(),
                    finance.getSalary(),
                    finance.getSalaryGrade()),
            JoinWindows.of(windowRetentionTimeMs), //30 seconds
            Joined.with(
                    employeeKeySerde,
                    employeeSerde,
                    financeSerde)).to(outputTopic, Produced.with(employeeKeySerde, employeeFinanceSerde));

如果在财务主题中,具有匹配键的记录在30秒后到达,则不会发生联接。关于如何解决此问题的任何见解都将有所帮助。预先谢谢你。

P.S .:此数据是虚构的。如果它与您的部门ID /薪水相符,则仅是巧合。 :)

1 个答案:

答案 0 :(得分:0)

如果在财务主题中,具有匹配键的记录在30秒后到达,则不会发生联接。

默认情况下,Kafka Streams使用24h宽限期,因此,即使有滞后或无序的数据,您的加入也应该起作用。请注意,Kafka中的 lag 始终引用 read 路径!

30秒钟后到达金融主题

但是,我认为您并不是真的有 lag 滞后(从某种意义上说,您回读了),但是上游的 write 被延迟了-在这种情况下,事件时间可能分配不正确:

请注意,在写入Kafka主题且您未明确指定时间戳时,生产者将在调用send()时分配时间戳,而不是在创建ProducerRecord实例时分配时间戳。如果要在创建ProducerRecord时分配时间戳,则需要将要分配的时间戳手动传递到构造函数中(不确定Spring Boot是否允许您执行此操作)。

作为替代方法(以防万一您无法显式设置记录时间戳),可以将时间戳嵌入值中(当然,这需要您更改EmployeeFinance类。这些数据可以通过Kafka Streams使用,您可以在自定义TimestampExtractor中使用它来获取自定义时间戳,而不是记录时间戳。