【问题标题】:Objectify doesn't store synchronously, even with nowObjectify 不同步存储,即使现在
【发布时间】:2012-12-22 04:44:36
【问题描述】:

我的 servlet 应该执行以下操作:当用户在某个场所注册时,我检查他当前是否在某个地方注册(即使它是同一个场所)如果是,请取消注册并再次注册他。

我有以下代码,为了显示我的问题,我已对其进行了简化:

    Date tempDate = new Date();


    Visit v = ofy().load().type(Visit.class)
            .filter(Visit.USER_ID, 5L)
            .filter(Visit.EXIT_DATE, null).first().get();

    if(v != null)
        exitVenue(5L, 7L, tempDate);

    Visit visit = new Visit(5L, 7L, tempDate);      
    ofy().save().entity(visit).now();

    Date tempDate2 = new Date();


    Visit v2 = ofy().load().type(Visit.class)
            .filter(Visit.USER_ID, 5L)
            .filter(Visit.EXIT_DATE, null).first().get();

    if(v2 != null)
        exitVenue(5L, 7L, tempDate2);

    Visit visit2 = new Visit(5L, 7L, tempDate2);        
    ofy().save().entity(visit2).now();
}


public void exitVenue(Long userID, Long venueID, Date exitDate) {

    Visit visit = ofy().load().type(Visit.class)
            .filter(Visit.USER_ID, userID)
            .filter(Visit.VENUE_ID, venueID)
            .filter(Visit.EXIT_DATE, null).first().get();

    if(visit == null){
        log.info("ERROR : User " + userID + " exited venue " + venueID + ", but Visit was not found");
        return;
    }
    visit.setExitDate(exitDate);

    ofy().save().entity(visit).now();
}

问题是,当我第二次执行所有这些操作时,它并不总是发现数据存储中已经有访问(每隔一次测试,左右)。而且我很困惑'now()'是否应该立即存储它然后才能继续运行?

非常感谢您的帮助, 丹

【问题讨论】:

  • 请注意,如果我使用调试工具运行它,一切正常。这就是为什么我认为这是一个速度问题。

标签: google-app-engine persistence google-cloud-datastore objectify


【解决方案1】:

发生这种情况是因为 GAE 数据存储区是 eventually consistent:当您创建/更新实体时,该方法会立即返回,但 indexes are still being built asynchronously。由于查询依赖于索引,因此您不会立即看到更改。

此外,这与 objectify 无关 - 这是底层数据存储的属性。同步写入 (.now()) 等待 提交阶段 完成,而异步甚至在此之前立即返回。

【讨论】:

  • 谢谢您的回答,还有两个问题:1. 我有什么办法可以用这个来加快交易速度,还是我只需要考虑什么时候设计我的应用程序? 2. 我以前在 GAE 和 JPA 工作过,从来没有注意到这一点,可以吗?
  • 我不确定为什么您没有注意到 JPA,除非您当时也在使用主/从数据存储(不再可用),它在从 Save 调用返回之前保存了它的索引。你无法改变这种行为,你只需要考虑它是如何工作的。
  • 文档声明下次执行读取时应用实体更改(= 写出索引):developers.google.com/appengine/articles/life_of_write。也许您应该尝试在写入后发出读取。
  • 谢谢彼得,但这没有帮助。好的。我想我会稍微改变一下我的设计。
  • 您可以通过将@parent 添加到您的数据存储实体并使用祖先查询来解决此问题。另一件事,如果你知道密钥并且可以执行 get(),那么你也不会遇到最终的一致性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-01
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多