当前位置: 首页 > 知识库问答 >
问题:

使用get_or_insert实现强一致性

仲孙子辰
2023-03-14

我有一个这样的模型:

class UserModel(ndb.Model):
    ''' model class which stores all the user information '''
    fname = ndb.StringProperty(required=True)
    lname = ndb.StringProperty(required=True)
    sex = ndb.StringProperty(required=True, choices=['male', 'female'])
    age = ndb.IntegerProperty(required=True)
    dob = ndb.DateTimeProperty(required=True)
    email = ndb.StringProperty(default=None)
    mobile = ndb.StringProperty(required=True)
    city = ndb.StringProperty(required=True)
    state = ndb.StringProperty(required=True)

由于以上字段都不是唯一的,所以电子邮件也不是唯一的,因为许多人可能没有电子邮件ID。因此,我使用以下逻辑创建字符串id

1. Take first two letters of 'state' and change it to upper case.
2. Take first to letters of 'city' and change it to upper case.
3. Get the count of all records in the database and increment by one.
4. Append all of them together.

我使用get_or_insert插入实体。

虽然添加用户不会经常发生,但任何冲突都会是灾难性的,这意味着竞争的可能性较小,但其影响非常大。

我的问题是:

1. Will using get_or_insert guarantee that I will never have duplicate IDs?
2. get_or_insert documentation says "Transactionally retrieves an existing 
   entity or creates a new one.". How can something perform an operation 
   "transactionally" without using a ancestor query.

PS:出于几个原因,我不能将所有用户实体保留在同一个实体组中。

共有2个答案

司马羽
2023-03-14

如果您保留该ID方案(老实说,您实际上不需要步骤1和2,只需要步骤3),那么就没有理由创建重复的ID。使用get\u或\u insert,它将查找您提供的确切ID,如果它存在,则将其提取,如果不存在,则只需创建它,如下所述。因此,您不能有重复的ID(如果您在模型中使用此ID作为强制密钥)。如果您遵循提供的链接,它会明确指出:

get和后续(可能的)put操作包装在事务中以确保原子性。这意味着get_or_insert()永远不会覆盖现有实体,并且仅当不存在具有给定类型和名称的实体时才会插入新实体。

事实上,它会进行html" target="_blank">事务处理,这意味着它会锁定实体组,以确保您没有争用。因为你似乎没有祖先,我想它只会锁定你正在更新的实体

欧阳博文
2023-03-14

为了提供事务性,get_or_insert使用Datastore事务。为了在事务中使用查询,它必须是祖先查询,但是事务也可以getput,它们不需要在实体上设置父级。

但是,正如@Greg提到的,您绝对不想使用此方案来生成用户ID。特别是,对数据库进行计数非常慢,并且不会扩展,并且最终是一致的。因为查询最终是一致的,所以只要结果最终是一致的,它可能会返回一个小于实际计数的计数(对于大型应用程序来说,这将一直是一致的)。这意味着您可以等待几个小时才能真正成功插入。

如果您想为客户ID提供州和城市,我建议执行以下操作:

  1. 使用自动ID执行put
  2. 向用户公开一个“客户ID”,即州级城市ID。
  3. 当您想要查找给定“客户ID”的客户时,只需对ID部分执行get
 类似资料:
  • 我正在努力实现强烈的一致性。让我们调用我的模型PVPPlayer: 模型的每个关键点都是这样创建的: 其中,配置文件是父模型: 我有2个REST api url: 在1)我做: 在2)我做: 我的流程如下所示: 问题: 使用保证了很强的一致性,所以我不明白的是为什么有时由于,我得到了一些陈旧的数据,比如点根本没有更新。 示例:

  • 这是我的简单实体: 我以这种方式加载我的食物清单: Key是为每个Food实体自动生成的。我也在使用HRD。因此...上面的查询(pm.newQuery(Food.class);)不具有很强的一致性,一次返回所有结果,第二次不返回新创建的食物。如何以这种方式更改此查询,以至于每次我从数据库中获取所有食物。在datastore留档中,我读过应该是祖先查询,但我没有祖先路径。(我应该说我是datast

  • 我想运行这个计划,以实现与我的GAE结构的高度一致性。目前,我有以下内容(我保证,这真的很简单): 您有一个类(类的意思是课堂不是编程“类”)模型和一个作业模型,还有一个用户模型。现在,一个类有一个名为MemberID的整数列表属性,它是一个用户ID的索引列表。类还具有赋值ID的字符串列表。 每当创建一个新的分配时,其相应的类实体也会更新,并将新的分配id添加到其列表中。 我想做的是为用户获取新的

  • 对于我的实验,我需要具体化一个由TBox/模式和ABox/数据组成的dbpedia本体论。 为此,我将dbpedia本体论/TBox/模式(http://downloads.dbpedia.org/2016-04/dbpedia_2016-04.owl)与DBPedia知识图中的ABox/data部分合并(我在http://downloads.dbpedia.org/2016-04/core-i1

  • 我目前是增强现实编程的新手,我想问一个关于AR应用程序的问题。我已经从play商店下载了“增强现实”应用程序。使用增强现实应用程序,我可以查看一些3D模型对象,如前视图、后视图、左侧和右侧视图。我已经从通用跟踪器的工作表中打印出来了,所以在通用跟踪器的帮助下,我可以查看一些3D模型对象。 例如,汽车或自行车可以放在通用跟踪器(打印表)上,然后可以在图形视图中查看对象。我可以理解,在“增强现实”概念

  • 我有一个3节点的Cassandra集群,其密钥空间的复制因子为3: (仅部署在一个数据中心) 当进行失败测试时,即关闭一个节点,我在尝试查询我的键空间时得到这些异常: 我不知道为什么会看到这个错误,因为: 我的复制因子设置为3(即我仍然有2个节点,每个节点包含所有数据) 我的一致性级别设置为QUORUM。(为什么我看到LOCAL_ONE?)