【问题标题】:Memcache and Eventual consistencyMemcache 和最终一致性
【发布时间】:2011-09-01 13:38:40
【问题描述】:

我正在开发一个小项目来了解 Google App Engine,该项目使用 Java 并具有 Customer 对象, Customer 的实例可以有一个策略。每个客户都在其自己的实体组中,因此交易可用于 修改客户。

网站的主页是客户列表,当添加新客户时,客户列表会再次显示。

由于每个客户都在自己的实体组中,因此有时新添加的客户不会出现在 新客户列表,几秒钟后刷新客户列表,客户就会出现。类似的问题 删除客户时存在,您删除客户但它会在整体列表中显示几秒钟。我明白 由于数据存储提供的最终一致性,这在 Google App Engine 中是可以预料的。

所以我尝试通过使用 memcache 来存储最近添加或最近添加的客户来解决这个问题 删除。我正在使用的代码如下。

public List<Customer> getCustomers() {
    List<Customer> cachedCustomers = myCache.getCached();
    List<Customer> recentlyDeleted = myCache.getDeleted();
    // Calls the real datastore.
    List<Customer> dbCustomers = customerDao.getCustomerList();
    Set<Customer> allCustomers = new HashSet<Customer>();

    //  Add cached first as these are most the most up todate.
    allCustomers.addAll(cachedCustomers);
    allCustomers.addAll(dbCustomers);
    allCustomers.removeAll(recentlyDeleted);

    List<Customer> allList = new ArrayList<Customer>();
    allList.addAll(allCustomers);
    Collections.sort(allList);        
    return allList;
}

我在这里问是因为我认为我这样做的方式并不觉得做这件事的“正确”方式,并希望 听取那些知道更好的方法来解决最终一致性产生的问题的人的意见。

【问题讨论】:

  • 为什么需要将每个客户放在不同的实体组中?您对客户进行了哪些交易?如果您确实需要客户列表始终是最新的,这意味着他们应该在同一个实体组中。只需根据您想要查看的内容定义实体组。此外,如果客户与单个用户相关,您可以使层次结构用户 -> 客户,然后使用用户作为祖先进行查询。此查询将返回最新的结果。
  • 存在防止每个实体每秒更新过多的性能限制。这个页面code.google.com/appengine/articles/scaling/contention.html 描述了它。我让每个客户都在自己的实体组中,客户因此我可以在交易中修改客户政策等。
  • 是的,实体组有大约 1 次更新/秒的限制,但您确定会超过此限制吗?您必须提供有关您的模型的更多信息,以便人们帮助您。如果客户属于单个用户,您可以毫无问题地拥有层次结构 User -> Customer -> Policy。
  • 通过将所有客户放在一个实体组中,整个站点每秒只能处理一次更新。那太慢了。客户不属于用户,所以我不能这样做。

标签: java google-app-engine


【解决方案1】:

你正在做的就是the docs recommends。所以我相信这是正确的做法。

另外,我在 Google 和 GitHub 上搜索了一个可以为您处理但找不到的库。因此,对于这种缓存最近插入和删除的方式感觉更“正确”,我建议您编写一个库来处理您想要的任何持久类。

另外,我建议阅读this post,其中 Google App Engine 的开发人员程序工程师 Ikai Lan 解释了提取和插入在 HR 中的工作原理以及与主/从数据存储相比对性能的影响。

【讨论】:

    【解决方案2】:

    使用 HRD,在 99.9% 的情况下,写入操作的结果应该在几秒钟内可见。因此,在典型的 Web 应用程序中,如果您作为操作的结果提供网页,则用户执行下一个操作之前的时间应该足以接收写入。

    因此,如果您从应用程序中的实时数据对象生成结果页面,您应该没问题。如果您将用户重定向到例如,您也应该没问题。一个客户页面,您可以在其中按 ID 读取客户(因为这是一致的)。

    如果您需要查询,并且您需要在操作后直接发出的查询中显示结果,我认为没有办法绕过 memcache,或者使用一些技巧来记录刚刚修改的对象的存在/不存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 2014-11-19
      • 1970-01-01
      • 2012-01-03
      • 2023-03-10
      • 1970-01-01
      相关资源
      最近更新 更多