App Engine,交易和幂等性

drh*_*yes 7 python google-app-engine transactions

请帮我找出我的误会.

我在App Engine上写了一个RPG.玩家采取的某些行动会消耗一定的数据.如果统计数据达到零,则玩家不再采取行动.不过,我开始担心会欺骗球员 - 如果一名球员很快就发出了两个动作,那就紧挨着了?如果递减stat的代码不在事务中,则玩家有机会执行两次动作.所以,我应该在事务中包装减少stat的代码,对吧?到现在为止还挺好.

但是在GAE Python中,我们在文档中有这个:

注意:如果您的应用在提交交易时收到异常,则并不总是意味着交易失败.在已提交事务并最终成功应用事务的情况下,您可以收到Timeout,TransactionFailedError或InternalError异常.尽可能使数据存储区事务处于幂等状态,这样,如果重复某个事务,最终结果将是相同的.

哎呦.这意味着我运行的函数看起来像这样:


def decrement(player_key, value=5):
  player = Player.get(player_key)
  player.stat -= value
  player.put()
Run Code Online (Sandbox Code Playgroud)

嗯,这不会起作用,因为事情不是幂等的,对吧?如果我在它周围放置一个重试循环(我需要在Python中吗?我已经读过我不需要在SO上...但我在文档中找不到它)它可能会增加两次值,对?由于我的代码可以捕获异常,但数据存储仍然提交数据......呵呵?我该如何解决?这是我需要分布式交易的情况吗?我真的吗?

mra*_*ted 13

首先,尼克的回答是不正确的.DHayes的事务不是幂等的,所以如果它被多次运行(即,当第一次尝试被认为失败时重试,当它没有时),那么该值将被多次递减.Nick说"数据存储区会检查实体是否已被修改,"但这并不能解决问题,因为两个事务具有单独的提取,第二次提取是在第一个事务完成之后.

要解决此问题,您可以通过创建"事务密钥"并将该密钥记录在新实体中作为事务的一部分来使事务具有幂等性.第二个事务可以检查该事务密钥,如果找到,将不执行任何操作.一旦您对交易完成感到满意,或者您放弃重试,就可以删除交易密钥.

我想知道AppEngine(百万分之一,或十亿分之一?)的"非常罕见"意味着什么,但我的建议是,在财务问题上需要进行幂等交易,但不是比赛得分,甚至"生命";-)