googleappengin中的竞争问题

2024-10-02 22:30:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我在googleappengine中遇到了争用问题,试着去理解到底发生了什么。在

我有一个带有注释的请求处理程序:

@ndb.transactional(xg=True, retries=5) 

…在这段代码中,我获取了一些东西,更新了一些其他的东西,但有时在请求过程中,日志中会出现这样一个错误:

^{pr2}$

…后面是堆栈跟踪。如果需要的话,我可以更新整个堆栈跟踪,但这有点长。在

我不明白为什么会这样。查看代码中出现异常的那一行,我在一个完全不同的实体上运行get_by_id(Round)。错误消息中提到的“PlayerGameStates”,名称“hannes2”是另一个实体GameState的父级,它在几行之前已经从数据库中get_async:ed

# GameState is read by get_async
gamestate_future = GameState.get_by_id_async(id, ndb.Key('PlayerGameStates', player_key))
...
gamestate = gamestate_future.get_result()
...

奇怪(?)问题是,该实体没有写入数据存储。如果在同一时间,我的理解也会发生同样的错误。。或者,如果在短时间内发生过多的写入操作。。在

但在阅读实体的时候也会发生这种情况吗?(“暂停发电机获取….”?)还有,这是在5点之后发生的吗ndb.交易重试。。?我在日志中看不到任何指示已重试的内容。在

非常感谢任何帮助。在


Tags: 代码实体id处理程序getasyncby堆栈
1条回答
网友
1楼 · 发布于 2024-10-02 22:30:32

是的,读操作和写操作都可能发生争用。在

在一个事务启动后,在您的例子中,当使用@ndb.transactional()注释的处理程序被调用时,任何被访问的实体组(通过读或写操作,并不重要)都会立即被标记为这样。在那一刻,不知道在事务结束时是否会有一个写操作-这根本不重要。在

争用错误太多(这与冲突错误不同!)指示太多并行事务同时尝试访问同一实体组。即使没有任何事务实际尝试写入,也可能发生这种情况!在

注意:这个争用是不是由开发服务器模拟的,只有在部署到GAE上,使用真实的数据存储时才能看到!在

更令人困惑的是事务的自动重试,这种情况可能发生在实际的写冲突或纯访问争用之后。在最终用户看来,这些重试可能是对某些代码路径的可疑重复执行—在您的案例中是处理程序。在

重试实际上会让事情变得更糟(在很短的一段时间内)-对已经访问量很大的实体组抛出更多的访问-我见过这样的模式,只有在指数退避延迟增大到足以让事务冷却一点(如果重试次数足够大的话)之后,事务已经允许事务正在完成。在

我的方法是移动推送队列任务上的大部分事务性内容,禁用事务和任务级别的重试,而是完全重新对任务进行排队—重试次数更少,但间隔更远。在

通常,当遇到此类问题时,必须重新访问数据结构和/或访问它们的方式(事务)。除了维护强一致性的解决方案(这可能相当昂贵),您可能需要重新检查一致性是否确实是必须的。在某些情况下,它被添加为一个笼统的要求,仅仅是因为它似乎简化了事情。从我的经验来看,没有:)

另一个可以帮助(但只是一点点)的方法是使用更快(也更昂贵)的实例类型-更短的执行时间转化为事务重叠的风险稍微降低。我注意到了这一点,因为我需要一个内存更大的实例,而这个实例恰好也更快:)

相关问题 更多 >