数据存储实体密钥冲突

时间:2012-05-14 14:59:59

标签: java google-app-engine google-cloud-datastore

在开发中,我有一个空的数据存储区。 在线我有一个拥有数百万实体的数据存储区。

在开发数据存储区(本地)中,我放了一个新实体(生成一个新密钥)。 然后我导出实体并将其放入在线数据存储区(在本地生成密钥)。在本地生成的密钥已经分配给在线数据存储区中的实体的风险是什么?

或者通过在本地创建密钥来避免冲突会更简单:

for (int i = 0; i < data.size(); i++) {
    Key k = KeyFactory.createKey(kind, new Date() + i);
    // continue to creating and inserting entities...
}

感谢。

4 个答案:

答案 0 :(得分:3)

来自https://developers.google.com/appengine/docs/java/datastore/entities

  

而不是使用键名字符串或生成数字ID   自动,高级应用程序有时可能希望分配   他们自己的数字ID手动到他们创建的实体。意识到,   但是,没有什么可以阻止数据存储区分配   您的一个手动数字ID到另一个实体。唯一的方法   避免此类冲突是让您的应用程序获取一个ID块   使用方法DatastoreService.allocateIds()或   AsyncDatastoreService.allocateIds()。数据存储区的自动ID   生成器将跟踪已使用这些ID分配的ID   方法,并将避免重复使用它们为另一个实体,所以你可以   安全地使用这些ID而不会发生冲突。

您必须手动生成所有数字键(以及永远不会发生冲突的方式)或使用allocateIds()。除非您使用该功能,否则无法保证您手动生成的任何内容都不会与现有密钥冲突。生成的键ID不像关系数据库中的自动增量字段,每次增加1。

答案 1 :(得分:0)

这取决于您在实体上拥有的ID类型。如果它们是整数,它们很小并且你很容易产生冲突。

我建议您创建一种与Google默认使用的格式略有不同的密钥格式。只要KeyFactory使用时钟的完整精度(即不会在几秒钟停止),上面的函数看起来就应该有效。

答案 2 :(得分:0)

当数据存储生成密钥时,ID为整数。如果您使用字符串作为ID生成密钥,则它们不会覆盖现有实体。

a.key.id() == 1
b.key.id() == '1'
a.key.id() != b.key.id()

答案 3 :(得分:0)

您应该提供有关您的用例的更多信息,以便任何人建议正确的解决方案。例如,您可以在dev数据库上创建密钥,如下所示:

  KeyFactory.createKey(entity, "dev_" + UUID.randomUUID())

另一种选择是创建一个小实用程序或应用程序,它将从本地数据库中检索实体,然后将其POST到开发数据库。获得POST的在线服务器将创建一个新的实体,并从客户端分配除密钥之外的所有属性,从而让GAE自动生成新密钥。然后可以将新密钥作为对POST操作的响应发送回客户端。

同样,我不知道您以后是否想要使用在线更新本地数据库的重新同步,但如果是这样,定义您自己的密钥的第一种方法将起作用,因为下一次同步将在线更新实体。 / p>