【发布时间】:2012-04-15 04:14:53
【问题描述】:
请帮我找出我的误解。
我正在 App Engine 上编写 RPG。玩家采取的某些行动会消耗一定的统计数据。如果统计数据达到零,则玩家不能再采取任何行动。不过,我开始担心作弊玩家——如果玩家非常快速地发送两个动作,紧挨着对方怎么办?如果减少统计数据的代码不在事务中,则玩家有机会执行该操作两次。所以,我应该将减少统计数据的代码包装在事务中,对吗?到目前为止,一切顺利。
不过,在 GAE Python 中,我们在 documentation 中有这个:
注意:如果您的应用在提交交易时收到异常,则不会 总是意味着事务失败。您可能会收到 Timeout、TransactionFailedError 或 在事务已提交并最终将要提交的情况下出现 InternalError 异常 申请成功。尽可能使您的 Datastore 事务具有幂等性,以便 如果您重复交易,最终结果将是相同的。
哎呀。这意味着我正在运行的函数如下所示:
def decrement(player_key, value=5):
player = Player.get(player_key)
player.stat -= value
player.put()
好吧,那是行不通的,因为它不是幂等的,对吧?如果我在它周围放置一个重试循环(我需要在 Python 中吗?我已经读过我不需要在 SO 上......但我在文档中找不到它)它可能会将值增加两次,对?由于我的代码可以捕获异常,但数据存储仍然提交数据......嗯?我该如何解决?这是我需要distributed transactions 的情况吗?真的吗?
【问题讨论】:
-
嗯,是的,这是一个很好的观点......但在我用一堆难以诊断、难以重现的错误乱扔代码之前,我想了解什么模式我应该去这里。
-
您的模式在正确的轨道上,但是 GAE 有很多令人沮丧的细微差别,使得像这样的手术精确实施变得困难。根据我使用 GAE 的经验,有时值得付出努力,有时则不然。
-
@TravisWebb 不同意。交易安全不是“过早的优化”,交易冲突也不是特别不可能。
-
@TravisWebb 有关“噩梦”的详细信息,请参阅我的答案。
标签: python google-app-engine transactions