我正在开展基于GAE的项目,涉及庞大的用户群(可能是数百万用户)。我们使用数据存储区来保持持久性。用户将通过用户名和电子邮件地址进行识别,因此这两个属性在所有类型的实体中应该是唯一的。由于数据存储区不支持ID以外的唯一字段,因此我们需要事务来确保在注册新用户时这些字段的唯一性。并且为了进行交易,用户实体需要包含在实体组中。
如here所述,不推荐使用大型实体组。因此,考虑到可能存在大量存储用户,我想将它们放入多个较小的实体组中。每个组都有一个共同的父级,其中ID来自两个唯一字段(例如,MD5总和的一部分)。插入新用户可能如下所示(在Python中):
@ndb.transactional
def register_new_user(login, email, full_name) :
# validation code omitted
user = User(login = login, email = email, full_name = full_name)
group_id = a_simple_hash(login, email)
group_key = ndb.Key('UserGroup', group_id)
query = User.query(ancestor = group_key).filter(ndb.OR(User.login = login, User.email = email))
if not query.get() :
user.put()
我在这个解决方案中看到的一个问题是,单独通过ID获取用户是不可能的。我们必须使用完整的实体密钥。
这种方法还有其他缺点吗?有人试过类似的东西吗?
修改
正如我在评论中指出的那样,上面列出的哈希值无法正常工作,因为它只会阻止注册具有非唯一电子邮件的用户以及与这些电子邮件匹配的非唯一用户名邮件。如果哈希是基于单个字段计算的,那么它将起作用。
尽管如此,我发现这种分片的概念本身很有趣,也许值得讨论。
答案 0 :(得分:0)
电子邮件地址由用户拥有并且是唯一的。所以有一个非常小的变化,有人会(尝试)使用相同的电子邮件地址。
所以我的approch将是:get_or_insert一个新的登录,这使得登录(通过密钥)变得容易,然后验证电子邮件地址是否是唯一的。
如果它不是唯一的,你可以丢弃或.....做别的事情
实体组对交易有意义。我对您计划的交易感兴趣,因为我不了解您的实体组密钥哈希。哪些实体将成为实体组的一部分,为什么?
具有相同登录名的用户将成为另一个实体组的一部分,如果我确实了解您的哈希值? 看起来您的实体组拥有一个实体。
答案 1 :(得分:0)
在我看来,你在这里过分思考:两个用户同时注册相同用户名的概率是多少? 非常苗条。对于这种情况,最终的一致性足够好,因为你没有纳秒精度...... 除非你计划拥有比Facebook更多的用户,否则人们每秒都会注册。
对于不同的用户,几乎不可能注册相同的电子邮件,因为电子邮件提供商已经为您完成了检查! 只有用户可以尝试使用相同的电子邮件地址打开两个帐户。对于这个查询,最终的一致性也足够了。
您的用户实体均属于自己的实体组。
实际上在大多数用例中,您的用户是最明显的根实体:人们使用数据存储区是因为它们需要可扩展性,并且大部分时间都需要面向用户的应用程序。