Google app engine 如何在身份验证期间防止Google App Engine/最终一致的数据存储中出现重复值

Google app engine 如何在身份验证期间防止Google App Engine/最终一致的数据存储中出现重复值,google-app-engine,jdo,eventual-consistency,Google App Engine,Jdo,Eventual Consistency,我们有一个认证系统,使用谷歌应用程序引擎作为后端。底层语言和框架包括Java、JDO、Google身份验证和Google应用程序引擎 我们有一个用户实体。用户实体是从Google App Engine身份验证响应中保存的用户元数据,例如:名字、姓氏、电子邮件地址 当用户尝试注册或登录两个登录事件时,我们扫描数据存储以查看是否已经存在具有相同电子邮件地址的用户。如果用户不存在,我们将创建一个新用户。如果用户确实存在,我们将更新并检索他们的用户信息,然后检索他们的应用程序数据 我们需要单独运行多个事

我们有一个认证系统,使用谷歌应用程序引擎作为后端。底层语言和框架包括Java、JDO、Google身份验证和Google应用程序引擎

我们有一个用户实体。用户实体是从Google App Engine身份验证响应中保存的用户元数据,例如:名字、姓氏、电子邮件地址

当用户尝试注册或登录两个登录事件时,我们扫描数据存储以查看是否已经存在具有相同电子邮件地址的用户。如果用户不存在,我们将创建一个新用户。如果用户确实存在,我们将更新并检索他们的用户信息,然后检索他们的应用程序数据

我们需要单独运行多个事务,因为登录页面与应用程序页面完全分离

在某些情况下,当用户在短时间内尝试注册两次时,会创建重复用户。虽然我们总是可以获取最后注册的用户,但我们确实希望查询是唯一的JDO查询。使用唯一的JDO查询,在事务内部运行的JDO查询有时会失败,因为用户的电子邮件地址有两个相同的值

我们考虑了以下实施约束的方法:

在缓存中存储新注册用户的信息。我们似乎没有找到任何信息表明缓存是防止重复的合适解决方案。缓存是否可以跨机器即时使用?即使是这样,缓存也可能出于各种原因弹出实体。 在会话中存储用户的电子邮件。这似乎使代码膨胀,似乎是一种奇怪的强制约束方式。
Google App Engine是否有一种最佳实践方法来防止身份验证工作流和单独事务期间出现重复值?

我建议将这两种方法结合使用:

创建一个登录实体,该实体由用户的电子邮件和主用户实体的id组成。使用户的电子邮件成为登录实体中的密钥。这确保了它的独特性。 额外的好处是,您可以将多个电子邮件地址链接到同一个用户实体。我们将此选项作为应用程序的一项功能

另一个额外的好处是:你可以用一个get呼叫代替你的登录查询,因为你可以从电子邮件地址创建一个密钥。这更便宜、更快,并避免了最终的一致性问题,因为get调用始终是一致的

在会话中存储电子邮件地址甚至一个简单的登录标志。添加它和在每次登录尝试时检查它只需要3-5行代码,所以我不会称之为膨胀。
在我的应用程序中,我向会话添加一个标志,并在每次调用应用程序引擎实例时检查该标志,不仅是登录调用,而且是所有调用,以确保额外的安全性,然后在用户注销时使会话无效。

嗨,Andrei,为了澄清1,您建议只使用电子邮件地址作为键值的keyfactory.createkey?是的。然后调用get,您将获得现有记录或EntityNotFoundException。