Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/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_Cqrs_Event Sourcing - Fatal编程技术网

Apache kafka 在Kafka上并发写入事件源

Apache kafka 在Kafka上并发写入事件源,apache-kafka,cqrs,event-sourcing,Apache Kafka,Cqrs,Event Sourcing,我一直在考虑在事件源配置中使用ApacheKafka作为事件存储。发布的事件将与特定资源关联,传递到与资源类型关联的主题,并按资源id分成分区。因此,例如,创建Folder类型和id为1的资源将生成FolderCreate事件,该事件将传递到“folders”分区中的主题,通过在主题中的分区总数上分片id 1。即使我不知道如何处理导致日志不一致的并发事件 最简单的场景是有两个可以使彼此失效的并发操作,例如一个更新文件夹,另一个销毁同一文件夹。在这种情况下,该主题的分区可能最终包含无效序列[Fol

我一直在考虑在事件源配置中使用ApacheKafka作为事件存储。发布的事件将与特定资源关联,传递到与资源类型关联的主题,并按资源id分成分区。因此,例如,创建Folder类型和id为1的资源将生成FolderCreate事件,该事件将传递到“folders”分区中的主题,通过在主题中的分区总数上分片id 1。即使我不知道如何处理导致日志不一致的并发事件

最简单的场景是有两个可以使彼此失效的并发操作,例如一个更新文件夹,另一个销毁同一文件夹。在这种情况下,该主题的分区可能最终包含无效序列[FolderDestroy,FolderUpdate]。这种情况通常通过对事件进行版本控制来解决,但卡夫卡不支持这种功能


在这些情况下,如何确保Kafka日志本身的一致性?

我认为使用Kafka进行聚合事件源(DDD意义上的)或“资源”是可能的。一些注意事项:

  • 使用每个分区(或多个分区)的单个进程来管理每个分区的串行写入。如果您负担不起回滚,请确保通过同一Kafka连接连续发送消息,并在向命令发送方报告成功之前使用ack=all。确保生产者进程跟踪每个资源的当前成功事件偏移量/版本,以便在发送消息之前自己进行乐观检查
  • 由于即使写入实际成功,也可能会返回写入失败,因此您需要重试写入并通过在每个事件中包括ID来处理重复数据消除,或者通过重新读取流中的(最近的消息)来重新初始化生产者,以查看写入是否实际工作
  • 以原子方式编写多个事件—只需发布包含事件列表的复合事件
  • 按资源id查找。这可以通过在启动时从分区读取所有事件(或从特定跨资源快照读取所有事件)并将当前状态存储在RAM或缓存在DB中来实现
  • 将以更简单的方式解决1,但似乎已停止


    卡夫卡溪流似乎为您提供了很多这方面的信息。例如,4是一个KTable,您可以让事件生成器在发送事件之前使用它来确定事件对于当前资源状态是否有效。

    您读过这个吗?如果每个分区只有一个进程,则不需要等待ACK—所有的处理都可以在该进程内序列化,而且就顺序/一致性而言,某些消息是否仍然在线并不重要(保证写入是一个单独的问题,可能不应同时混入解释)但是,如果资源1、事件写入A失败,但您在不等待A的确认的情况下写入事件B,而B写入ok呢?那么B在流中没有A,打破了不变量。或者A以某种方式延迟,并在B之后进入流。或者这是不可能的,因为两者都将使用相同的TCP连接?无论如何,如果可以的话,这将简化一些事情是这样的。我认为不可能将事件A和B从单个程序发送到单个kafka频道,然后在那里只发送B。它将是nothing、A only或A和B。生产者连接是具有重新连接的无损TCP流。当然,如果你故意搞砸了你的kafka代理(将消息删除时间设置为几秒钟,在处理过程中重新启动,清理内容等)一切都是可能的,但在正常操作中(即使有错误),事件不应该从生产者流的中间丢失。恐怕这是可能的,我们已经看到这种情况发生。生产者发送A,代理拒绝它,因为重新平衡刚刚发生,它不再是该分区的领导者。生产者发现新的领导者并发送B。B已存储,但A未存储。如果您喜欢thr,请仅使用acks=0应该考虑一致性,并愿意为(相对而言)消息丢失付出代价正常操作。对于#2,我强烈建议不要在再次发布之前尝试读取流的内容,以确定某个记录之前是否已发布,以避免重复。这会使制作人的实现大大复杂化。卡夫卡背后的一般设计理念至少是一次交付表示消费者生态系统中的幂等行为。您的消费者应该已经能够处理重复事件。