【问题标题】:changing datastore entires via remote api is not reflected on running instances通过远程 api 更改数据存储整体不会反映在正在运行的实例上
【发布时间】:2013-05-06 21:07:19
【问题描述】:

我正在通过 Java 中的远程 API 更新数据存储中的整体。

如果我在应用引擎仪表板中查询更新的条目,我可以看到新版本。 但是我的 servlet 在更新之前运行的实例上运行并且已经服务读取数据存储条目仍然看到旧版本。

如果我手动关闭实例并启动一个新实例,它就可以正常提供新版本。 如果我通过应用引擎仪表板从数据存储中删除条目,则旧运行实例无法再按预期读取该条目。

这似乎是运行实例的缓存问题。似乎远程 API 无法告诉正在运行的实例某些数据存储条目无法再缓存。

我可以在远程 API 上做些什么来改变它吗? 还是我应该提交错误?

注意: 我没有在 memcache 或实例的 RAM 中缓存任何内容。

更新 这就是我通过远程 API 更新新实体的方式:

DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
Entity entity = new Entity("DocModel", "somekey");
entity.setProperty("html", "someProperty");
ds.put(entity);

这是使用 JDO 通过 servlet 读取值的方式:

PersistenceManager pm = PMF.get().getPersistenceManager();
DocModel docModel = pm.getObjectById(DocModel.class, "someKey");

这是 JDO 类:

@PersistenceCapable
public class DocModel {
  @PrimaryKey
  @Persistent
  private String name;

  @Persistent
  private Text html;

  public DocModel(String path, String html) {
    this.name = path;
    this.html = new Text(html);
  }

  public String getHtml() {
    return html.getValue();
  }

  public String getPath() {
    return name;
  }
}

更新2

这似乎与 JDO 相关。我将读取更改为使用数据存储 API,现在我看到了更新的值。使用 JDO,这些更新的值将永远不会被看到(我测试了大约 10 分钟几次)。我需要杀死实例以传播值。

【问题讨论】:

    标签: google-app-engine


    【解决方案1】:

    听起来像是一个一致性问题(如果您 100% 确定没有缓存条目/PMF 正在进行)。

    您确定 JDO 使用的是强一致性吗?您可以通过

    强制设置
    Query q = pm.newQuery(DocModel.class);
    q.addExtension("datanucleus.appengine.datastoreReadConsistency", "STRONG");
    

    Imho JDO 默认使用强一致性(在 jdoconfig.xml 中指定),但我会仔细检查 jdoconfig.xml)。

    更新:强一致性不是 JDO 的默认设置(尽管文档是这样说的)=> 因此,您所看到的内容是有意义的,将一致性设置为 STRONG 可能会解决您的问题 (@987654323 @)。

    【讨论】:

    • 除非您有祖先查询,否则强一致性将不起作用。
    • 这是一个 JDO 问题。删除 JDO 并直接使用数据存储 API 似乎可以修复它。 JDO 似乎在某处缓存了很长时间的值。我对最终的一致性很好,但是对于 JDO,似乎永远无法实现更改(尝试了 10 分钟几次)
    • 我不敢问-但是你是在使用后关闭pm吗? (pm.close();) 我的意思是 - 通常 PMF/pm 是静态的,也许这会导致根本原因......只是猜测......
    【解决方案2】:

    那是eventual consistency,如果您想确保在查询中看到所有最新写入,则需要运行祖先查询

    【讨论】:

      【解决方案3】:

      听起来不像是一个错误,您需要自己明确清除内存缓存。如果您的实例缓存在本地内存中,您还必须自己清除它。这些都不是数据存储 api 的一部分。

      【讨论】:

      • 我没有使用 memcache 或缓存在实例的 RAM 中
      • 您在 Java 中使用什么库/框架?你确定它不会在后台使用 memcache 吗?您的实例必须根据您对所遇到行为的描述来缓存某些内容。您在更新后执行查询的速度有多快,您可能还会看到 HRD 在工作中的最终一致性。您可能应该提供更多详细信息 - 查询类型、放置和查询之间的时间范围。我一直使用远程 api,除了实例/memcache 缓存生效时,从未遇到过您描述的问题。
      • 显示一些关于如何进行提取的代码会产生巨大的影响。如果您不进行任何缓存,则可能是最终的一致性行为。但这将取决于您如何获取数据 - 一些获取操作(如 get-by-key/id 或事务)将完全一致。除非您或您的框架正在缓存,否则 GAE 本身不会对您的实例进行任何自动缓存。
      • 如果您自己或您的框架没有明确指示,数据存储将不会缓存在 Memcache 中(cfr. objectify)。您应该自己明确清除内存缓存是不正确的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 2015-02-20
      • 2012-02-27
      相关资源
      最近更新 更多