客观化:处理竞争条件以防止重复的帐户创建

编程入门 行业动态 更新时间:2024-10-25 11:33:39
本文介绍了客观化:处理竞争条件以防止重复的帐户创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正尝试为用户(Google用户)创建一个帐户,因此我需要检查用户是否存在,如果不存在,为该用户创建一个帐户,但是我面临的事实是,如果我滥用createAccount API方法,帐户有时会创建两次。

@ApiMethod(name =account.google.create) public Account createGoogleAccount(最终用户用户)抛出OAuthRequestException { if(user == null ){抛出新的OAuthRequestException(createAccount:OAuthRequestException<用户未被认证>); } Account alreadyExisting = RObjectifyService.getObjectify()。load().type(Account.class).filter(accountId.GOOGLE,user.getUserId())。filter(email, user.getEmail())第一()现在()。; if(alreadyExisting!= null){抛出新的OAuthRequestException(createAccount:OAuthRequestException<帐户已存在>); } return RObjectifyService.getObjectify()。transactNew(new Work< Account>(){ @Override public Account run(){ Account account = AccountProvider .createAccountFromGoogleProvider(user); RObjectifyService.save(account); return account; } }); }

我读过我应该使用事务,但我不能,因为如果我做这在交易中:

RObjectifyService.getObjectify().load().type(Account.class).filter(accountId .GOOGLE,user.getUserId())。filter(email,user.getEmail())。first()。now()

我得到一个错误只有祖先查询被允许在事务内部,但我没有看到另一种方法去做它

这是正确的方法吗?

谢谢 您需要一个事务,并且您需要一个实体,其主键是您尝试创建唯一的值(即用户名)。

该模式有点棘手。 此处有一些讨论。伪代码的基本思想是: $ ul $ li $ start $ b

  • 使用唯一PK加载实体
  • li>
  • 如果有实体
    • 中止并返回重复错误
  • else
    • 使用唯一的PK创建实体(+您需要额外的工作)
    • 提交事务如果提交失败
      • 中止并返回重复错误
    • 其他
      • 一切都很棒!

    您可能不希望使用用户名作为您的主键用户实体,因此创建一个单独的用户名实体并混合创建用户名与 User 在同一个事务中。一定要保留用户名实体;这就是保证唯一性的原因。

    这个问题(唯一性)实际上是像GAE数据存储这样的大规模分布式系统中更具技术挑战性的问题之一。只有传统的RDBMS是单主机系统才能在传统的RDBMS中解决问题,这对于可扩展性和容错性产生了影响。 GAE为您提供必要的原语以强化集群范围的独特性;他们只是不容易使用。

    I'm using Google App Engine and Datastore with objectify.

    I'm trying to create an account for a user (Google user), so I need to check if that users exist, and if not, create an account for that user, but I'm facing the fact that sometimes the account is created twice if I spam the createAccount API method

    @ApiMethod(name = "account.google.create") public Account createGoogleAccount(final User user) throws OAuthRequestException { if (user == null) { throw new OAuthRequestException("createAccount: OAuthRequestException<User is not authenticated>"); } Account alreadyExisting = RObjectifyService.getObjectify().load().type(Account.class).filter("accountId.GOOGLE", user.getUserId()).filter("email", user.getEmail()).first().now(); if (alreadyExisting != null) { throw new OAuthRequestException("createAccount: OAuthRequestException<Account already exist>"); } return RObjectifyService.getObjectify().transactNew(new Work<Account>() { @Override public Account run() { Account account = AccountProvider.createAccountFromGoogleProvider(user); RObjectifyService.save(account); return account; } }); }

    I read that I should use transactions but I can't because if I do this in the transaction:

    RObjectifyService.getObjectify().load().type(Account.class).filter("accountId.GOOGLE", user.getUserId()).filter("email", user.getEmail()).first().now()

    I get an error "Only ancestor queries are allowed inside transactions", but I don't see another way to do it

    Is this the right way to do it?

    Thanks

    解决方案

    You need a transaction and you need an entity whose primary key is the value you are trying to make unique (ie the username).

    The pattern is a little tricky. There is some discussion of it here. The basic idea in pseudocode is:

    • start transaction
    • load entity with the unique PK
    • if there is an entity
      • abort and return duplicate error
    • else
      • create the entity with the unique PK (+ whatever extra work you need)
      • commit the transaction
      • if the commit fails
        • abort and return duplicate error
      • else
        • everything is great!

    You probably don't want to make username the primary key of your User entity, so create a separate Username entity and mix in creation of Username with User in the same transaction. Be sure to leave the Username entity around; that's what guarantees uniqueness.

    This problem (uniqueness) is actually one of the more technically challenging problems in a massively distributed system like the GAE datastore. It's simple to solve in a traditional RDBMS only if the traditional RDBMS is a single-master system, with the resulting impact on scalability and fault tolerance. GAE gives you the necessary primitives to enforce clusterwide uniqueness; they just aren't super easy to use.

  • 更多推荐

    客观化:处理竞争条件以防止重复的帐户创建

    本文发布于:2023-10-23 19:49:09,感谢您对本站的认可!
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:帐户   条件   竞争   以防止   客观化

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!