并发写在Kafka之上的事件采购

时间:2017-06-04 20:56:21

标签: apache-kafka cqrs event-sourcing

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

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

在这些情况下,可以采取哪些措施来确保Kafka日志本身的一致性?

1 个答案:

答案 0 :(得分:4)

我认为可能使用Kafka来进行聚合(DDD意义上的)或“资源”的事件采购。一些说明:

  1. Serialise每个分区写入一次,每个分区(或多个分区)使用一个进程来管理它。确保以相同的Kafka连接顺序发送消息,并在向命令发送方报告成功之前使用ack = all,如果您无法承受回滚。确保生产者进程跟踪每个资源的当前成功事件偏移/版本,因此它可以在发送消息之前进行乐观检查。
  2. 由于即使写入实际成功也可能返回写入失败,因此您需要通过在每个事件中包含ID来重试写入并处理重复数据删除,或者通过重新读取(最近的消息)重新初始化生成器流,以查看写实际是否有效。
  3. 以原子方式编写多个事件 - 只发布一个包含事件列表的复合事件。
  4. 按资源ID查找。这可以通过在启动时从分区读取所有事件(或从特定跨资源快照中读取所有事件),并将当前状态存储在RAM中或缓存在数据库中来实现。
  5. https://issues.apache.org/jira/browse/KAFKA-2260会以更简单的方式解决1,但似乎停滞不前。

    Kafka Streams似乎为您提供了很多这样的功能。例如,4是KTable,您可以让事件生产者使用一个来确定事件在发送之前是否对当前资源状态有效。