首页 > 解决方案 > 如何在 axon 中实现读(查询)模型和写(命令)模型之间的完全一致性

问题描述

我有 2 个 spring-boot 服务充当命令和查询,如下所示。

  1. Command-Service:负责处理命令、事件、维护聚合状态并将数据存储到数据库中。
  2. Query-Service:负责处理查询以从数据库中获取数据。

请注意,这两个服务共享相同的 axon-server 实例和相同的数据库(在本例中为 ElsaticSearch)。

我的 UI 的设计方式是,当用户提交表单以创建数据时,会发生一个 ajax 调用,然后按以下顺序执行 2 个 rest 调用:

  1. 第一个调用是一个 post 请求,它发送到 Command-Service,执行如下:
    • 使用 formdata 创建一个 CreateDataCommand 对象并触发如下:
    org.axonframework.commandhandling.gateway.CommandGateway.sendAndWait(CreateDataCommand);
    
    • CreateDataCommand 在触发 DataCreatedEvent 的聚合中处理:
    @CommandHandler
    private DataAggregate(CreateDataCommand createDataCommand  ) {
       AggregateLifecycle.apply(new  DataCreatedEvent ());
    }
    
    • DataCreatedEvent 在 2 个地方处理,
      1. 在聚合本身中,聚合更新它的状态:
      @EventSourcingHandler
      private void on(AppCreatedEvent appCreatedEvent) {
         // updated aggregate's state
      }
      
      1. 在 Projection 中,将数据保存到数据库中。
      @EventHandler
      private void on(AppCreatedEvent appCreatedEvent) {
        // Saves data to database.
      }
      
  2. 成功执行上述操作后,ajax 立即向 Query-Service 发送 get 请求,执行如下:
    • 触发 GetDataQuery 查询,如下所示:
      org.axonframework.queryhandling.QueryGateway.query(GetDataQuery, ResponseType);
      
    • GetDataQuery 被处理以从数据库中获取数据,如下所示:
      @QueryHandler
      List<Data> getData(GetDataQuery getDataQuery){
        // hits the databse and returns data.
      } 
      

问题:即使数据通过 Command-Service 保存到数据库中,对 Query-Service 的调用也会被触发并且它总是返回空列表。在第二次调用之后,它会返回正确的数据。发生这种情况是因为 Query-Service 在 Command-Service 完成在数据库中创建数据之前命中数据库。

ajax脚本:

    $.ajax({
        type: "POST",
        url: "directs to Command-Service to save data",
        data: formData,
        contentType: false,
        processData: false,
        cache: false,
        timeout: 60000,
        enctype: "multipart/form-data",
        success: data => {
            setTimeout(() => location.replace("url of query-service"), 1000);
        }
});

有人可以帮助我实现完全一致性或找到一种方法来消除由于上述现象而发生的不一致。

标签: spring-bootaxon

解决方案


推荐阅读