Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache kafka 如何使用Kafka流处理无序的事件_Apache Kafka_Apache Kafka Streams - Fatal编程技术网

Apache kafka 如何使用Kafka流处理无序的事件

Apache kafka 如何使用Kafka流处理无序的事件,apache-kafka,apache-kafka-streams,Apache Kafka,Apache Kafka Streams,我有一个应用程序,其中基于用户操作(如用户登录、用户中间操作(可选)和用户注销)发送卡夫卡主题的事件。每个事件在事件对象中都有一些信息以及userId,例如登录事件有loginTime;添加注释具有注释(中间操作)。类似地,注销事件具有logoutTime。需求是在接收到每个用户的注销事件并将其发送到下游后,将所有这些事件中的信息聚合到一个对象中 由于某些原因(网络延迟、多个事件生成器),事件可能没有按顺序出现(用户注销事件可能出现在中间事件之前),因此问题是如何处理此类场景?我不能在收到用户注

我有一个应用程序,其中基于用户操作(如用户登录、用户中间操作(可选)和用户注销)发送卡夫卡主题的事件。每个事件在事件对象中都有一些信息以及userId,例如登录事件有loginTime;添加注释具有注释(中间操作)。类似地,注销事件具有logoutTime。需求是在接收到每个用户的注销事件并将其发送到下游后,将所有这些事件中的信息聚合到一个对象中

由于某些原因(网络延迟、多个事件生成器),事件可能没有按顺序出现(用户注销事件可能出现在中间事件之前),因此问题是如何处理此类场景?我不能在收到用户注销事件后等待中间事件,因为根据用户的操作,中间事件是可选的


在这里,我认为唯一的选择是在收到用户注销事件后等待一段时间,如果在该等待时间内收到,则处理中间事件并发送已处理的事件,但同样不确定如何实现这一点。

Kafka
不保证
主题上的顺序,它保证
分区上的顺序。一个主题可以有多个分区,因此使用您的主题的每个使用者都将使用一个分区。这就是卡夫卡实现可伸缩性的方式。所以你所经历的是正常的行为(它不是bug或与网络延迟或类似的事情相关)。您可以做的是确保所有要按顺序处理的消息都发送到同一分区。您可以通过将分区数设置为1来实现这一点,这是最愚蠢的方法。当您使用producer发送消息时,默认情况下kafka会查看密钥,对其进行散列,并通过该散列知道应该在哪个分区上发送消息。您可以确保所有消息的密钥都相同。这样,所有密钥的散列都将是相同的,所有消息都将转到同一分区。此外,您还可以实现自定义分区器,并覆盖kafka选择哪个分区消息的默认方式。这样,所有消息都将按顺序到达。如果您不能执行这些操作,那么您将收到无序的事件,您必须考虑如何无序地使用它们,但这与卡夫卡无关。

如果您无法保持事件的顺序(注销将是最后一个事件), 您可以使用Kafka Streams实现您的需求。Kafka Streams DSL可以与处理器API结合使用(更多详细信息)

您可以有多个分区,但特定用户的所有事件都必须发送到同一分区

您必须实现自定义处理器/转换器。 您的处理器将把每个事件/活动放入状态存储(将特定用户的所有事件聚合到同一个键下)。 处理器API使您能够创建某种调度器()。
您可以为特定用户安排每X秒检查一次事件。如果注销早在很久以前,您将获得所有事件/活动,并进行一些聚合,并将结果发送到下游。

如其他答案所述,在卡夫卡中,顺序是基于每个分区维护的

既然您正在谈论用户事件,为什么不将UserID作为您的卡夫卡主题键?因此,与特定用户相关的所有事件都将始终被订购(前提是它们由单个生产者生产)

您应该确保(按设计)只有一个卡夫卡制作人将所有用户更改事件推送到给定主题。通过这种方式,您可以避免由于多个生产者而导致的无序消息

在streams中,您可能还希望查看Kafka streams中的窗口。例如,非重叠和固定大小。您可以在一段时间内聚合记录

现在,您可能希望按照时间戳(或者您说您有注销时间、登录时间等)对聚合的数据进行排序,并相应地采取行动


简单有效的解决方案

使用同步发送并将
delivery.timeout.ms
retries
设置为最大值。 要确保容错,请使用
min.insync.replicas=2
(主题配置)设置
acks=all
,并使用单个生产者推送到该主题。 您还应该将
max.block.ms
设置为某个最大值,以便在获取元数据时出现错误时(例如,当Kafka关闭时),您的
send()
不会立即返回

将同步发送与您的速率进行基准测试,并检查它是否符合您的要求或基准数字

这样可以确保先发的消息首先发送给卡夫卡,然后在成功确认前一条消息之前,不会发送下一条消息

如果你的基准数据没有达到,试试背压 类似内存/持久队列的机制

  • 将事件添加到线程1中的队列
  • 线程2中队列中的Peek(非出列)事件
  • 在线程2中调用
    producer.send(…).get()
  • 将线程2中的事件出列

  • 您能详细解释一下,您想说什么吗?@Swapnil,请先阅读附件中的链接,然后如果您有任何问题,请询问我Superss API是否应该允许用户传递自定义逻辑(就像窗口聚合)
    ,但这与卡夫卡无关
    ——为什么不?这是绝对相关的!