按数字ID创建唯一的应用引擎数据存储区实体,不会发生冲突 - python

时间:2016-01-15 00:40:56

标签: python google-app-engine app-engine-ndb google-cloud-datastore

当多个人可能尝试同时创建实体时,我正在尝试为实体创建一个没有冲突的数字ID(应用程序用户会看到并使用该ID,因此理想情况下它将低于6位数长度 - 自动分配的ID可能是不可接受的)。

我目前的解决方案似乎过于繁琐,甚至可能无法解决冲突。

我有一个ID计数器,我将其存储在另一个App实体中:

class App(ndb.Model):
    # counter to store number of projects
    num_projects     = ndb.IntegerProperty(default = 0)

实际项目:

class Project(ndb.Model):
    date_created  = ndb.DateTimeProperty(auto_now_add = True)
    last_modified = ndb.DateTimeProperty(auto_now = True)

    owner       = ndb.KeyProperty(required = True)
    owner_name  = ndb.StringProperty(required = True)

    name        = ndb.StringProperty(required = True)

和用于创建项目的处理程序类:(可以同时调用)

def make_new_project(self):
    pdt = App.by_id('pdt')
    pdt.num_projects = pdt.num_projects + 1
    if not Project.by_id(pdt.num_projects):
        project = Project(id=pdt.num_projects)
        project.put()
        pdt.put()
        return project
    else:
        return self.make_new_project()

处理程序的意图是检查项目ID是否已被使用(有人在我检索App计数器之后确实放了一个新项目),如果没有,用新计数器编号创建项目,然后将两者都存储到DB。

我觉得这仍然有点儿,可能会导致竞争条件?有没有更好的办法?我应该预先分配密钥吗?如果是,我该怎么做?我是否将分配的密钥存储到我的App模型中以便以后检索?

我很容易对某些功能的运行时感到困惑。如果我添加一个函数来为我的main.py分配密钥,那么每次启动一个新实例时都会运行吗?

为了澄清下面提出的一些问题,项目应该可以通过nuerics找到,因为现有系统的用户更喜欢在与其他员工交谈时引用项目编号...即:“我正在打电话给项目13670“并且他们可以通过顺序编号判断哪个项目较旧,否则我只会生成一个随机的5位数字,并在分配之前检查它是否尚未使用。

任何帮助,澄清等......都将不胜感激。

1 个答案:

答案 0 :(得分:1)

使用NDB生成的密钥:它是为多个并发而设计的,并且做得很好。

然后将生成的密钥转换为更友好的密钥:base36应该可以解决问题。

例如:

9999999999999999 (16 length)

变为

2QGPCKVNG1R (11 length)

具体做法是:

friendlyValue = base36encode(entity.key.id())