如何确保 GAE 上的 MemCache 和 Datastore 之间的一致性?

Posted

技术标签:

【中文标题】如何确保 GAE 上的 MemCache 和 Datastore 之间的一致性?【英文标题】:How do I ensure consistency between MemCache and Datastore on GAE? 【发布时间】:2012-11-29 09:21:37 【问题描述】:

我正在使用事务将多个实体写入数据存储。我也想将这些实体保留在 MemCache 中。如何确保 MemCache 中的实体副本实际上等于 Datastore 中的副本?

例如我能做到:

tx.begin()
datastore.put(entity)
if (memcache.putIfUntoched(key, entity))
  tx.commit()

但是,如果事务失败,实体可能会在 MemCache 中结束,而不是在 Datastore 中。另一方面,如果我这样做:

tx.begin()
datastore.put(entity)
tx.commit()
memcache.putIfUntoched(key, entity))

那么数据存储事务可能会成功,但 MemCache 更新可能会失败。如何确保一致性?

【问题讨论】:

我想,如果你使用 NDB,NDB 会小心的。 我的应用是 Java :-( NDB 是怎么做的? 对不起,我不明白你使用 Java。 NDB 是大师的一个项目:Guido van Rossum。顺便一提。在 Python 中,我从未见过 memcache 更新失败。 Memcache 集没有任何异常或返回码。但是您可以检测功能 API 的问题。我发现了这个:osdir.com/ml/GoogleAppEngine/2009-10/msg00437.html memcache.put() 很可能永远不会失败,但 putIfUntouched() 在并发更新时会失败。 【参考方案1】:

根据我的经验,如果同时写入数据库和缓存,它可能没有那么有用。一般来说,将数据库事务与其他东西(例如文件系统)混合起来很难。

我建议你改变你的程序逻辑,这样

    创建新记录时,仅写入 DB 当您更新现有记录、写入数据库并使缓存中的相应插槽无效时 在查找记录时,只需检查缓存即可。如果不存在,则从数据库加载并填充缓存

【讨论】:

感谢您的反馈。您的解决方案很容易实施,但它闻起来像是一种解决方法。对于经常使用但很少更新的实体,缓存失效策略是可以的,但是我有一些经常更新的实体(例如资源计数器),我希望从 MemCache 中获取它们以前的值并消除数据存储读取。 哦还有一件事:如果您驱逐缓存,您如何确保删除操作与数据存储同步?例如。当另一个请求在你提交之后但在你被驱逐之前同时从内存缓存中获取对象时,你不会遇到同样的问题吗? @Michael 只要其他请求看到的一致就可以了,就像MVCC for DB transactions一样。所以你也可以指定一个超时时间,而不是显式地使缓存项失效。 @Michael 缓存不是事务性的,因此不支持像关系数据库那样的一致性。而且不需要,肖的逻辑解决方案很常见。如果发生读取和写入/删除请求几乎同时出现,那么读者得到什么(写之前或之后的日期......)并不重要,因为它是一个 Web 应用程序,他可以再次发出请求。但如果事务是导入的,则不要使用缓存,使用关系数据库,创建适合您的性能需求的 ER 模式并在集群中运行。 @Michael 并作为 GAE 的提示,检查此实体的缓存命中率。如果低于 50%,最好改成优化的数据库实体,不要使用缓存,因为每次从缓存中写入和读取也会花费 GAE 时间。

以上是关于如何确保 GAE 上的 MemCache 和 Datastore 之间的一致性?的主要内容,如果未能解决你的问题,请参考以下文章

python gae-memcache-decorator.py

Eclipse+PyDev+GAE memcache“来自导入的未定义变量:get”

GAE DataStore 如何支持事务?

GAE:确保外部任务真正完成的首选方法是啥?

如何在 GAE 中设置路由以进行反应?在基本 create-react-app 上的 GAE 中,通过 URL 直接路由到 react-router-dom 路由失败?

GAE 上的 BigQuery:根据开发人员的访问权限运行数据