GAE查找表与交易不兼容?

时间:2011-09-16 22:55:28

标签: python google-app-engine transactions google-cloud-datastore entity-groups

我的Python高复制数据存储区应用程序需要一个介于100,000到1,000,000个条目之间的大型查找表。我需要能够为某些方法提供代码,该方法将返回与该代码关联的值(如果没有关联,则返回None)。例如,如果我的表格中有可接受的英语单词,那么我希望函数在找到单词时返回True,否则返回False(或None)。

我目前的实现是为每个表条目创建一个无父实体,并为该实体包含任何关联数据。我将该实体的数据存储区密钥设置为与我的查找代码相同。 (我将所有实体放入自己的命名空间以防止任何键冲突,但这对于这个问题并不重要。)然后我只需在代码上调用get_by_key_name()并获取相关数据。

问题是我在交易期间无法访问这些实体,因为我试图跨越实体组。回到我的例子,假设我想拼写检查聊天会话中使用的所有单词。我可以访问聊天中的所有消息,因为我给他们一个共同的祖先,但是我无法访问我的单词表,因为那里的条目是无主义的。我必须能够在交易期间引用该表。

请注意,我的查找表已修复,或者很少更改。这再次匹配拼写检查示例。

一种解决方案可能是在一次交易中加载聊天会话中的所有单词,然后拼写检查它们(保存结果),然后启动第二个事务,对所保存的结果进行拼写检查。但这不仅效率低下,聊天会话可能已添加到事务之间。这似乎是一个笨拙的解决方案。

理想情况下,我想告诉GAE查找表是不可变的,因此我应该能够查询它而不会抱怨事务中的跨越实体组。但是,我认为没有办法做到这一点。

在memcache中存储表条目很有诱惑力,但这也存在问题。这是一个大量的数据,但更麻烦的是,如果GAE引导一个memcache条目,我将无法在事务中重新加载它。

有没有人知道大型全局查找表的合适实现?

请理解我不是在寻找拼写检查网络服务或类似的东西。我使用单词查找作为示例只是为了使这个问题清楚,我希望为任何类型的大型查找表提供一般解决方案。

2 个答案:

答案 0 :(得分:1)

首先,如果您认为命名空间有助于避免关键冲突,那么就该退一步了。密钥由实体类型,命名空间,名称或ID以及实体可能拥有的任何父级组成。对于具有相同名称或ID的两种不同实体类型,它是完全有效的。因此,如果您有一个匹配的LookupThingy,并且通过指定唯一名称创建了每个成员,则该密钥不会与其他任何内容发生冲突。

对于在事务中对无代表的查找表执行等效拼写检查的挑战,是否可以将查找表保留在代码中?

或者你能想到一个更接近你需要的类比吗?是否需要在事务中进行查找?

答案 1 :(得分:1)

如果可以,请尝试将数据放入实例内存中。如果它不适合实例内存,您可以选择几个选项。

您可以将数据存储在使用应用程序上载的资源文件中(如果它只是不经常更改),并从磁盘上访问它。这假设您可以构建一个允许轻松查找磁盘的数据结构 - 实际上,您正在实现自己的只读磁盘表。

同样,如果它太大而不适合作为静态资源,您可以采用与上面相同的方法,但将数据存储在blobstore中。

如果您的数据绝对必须位于数据存储区中,则可能需要模拟自己的读取 - 修改 - 写入事务。在记录中添加“修订”属性。要修改它,请获取记录(在事务外部),执行所需的更改,然后在事务内部再次获取它以检查修订值。如果它没有更改,请在您自己的记录上增加修订并将其存储到数据存储区。

请注意,底层的RPC层理论上支持多个独立的事务(以及非事务性操作),但是API目前没有暴露任何方式从事务中访问它,没有可怕的(我的意思是非常可怕)不幸的是,黑客攻击。

最后一个选项:您可以运行配置了更多内存的后端,公开“SpellCheckService”,并从您的前端对其进行URLFetch调用。请记住,内存总是比任何基于磁盘的选项快得多。