我正在以Java风格使用Google Appengine,并且正在尝试执行以下操作:

1-创建一个属性COUNT为0的实体。

2a-启动执行一些网络调用的任务队列任务,并更新同一实体的STATUS属性(使用Datastore#put

2b-同时,在原始“线程”中,为COUNT保存一个不同的数字。 (也使用Datastore#put

鉴于2a2b可能在同一时刻并行完成,但是它们更新了两个不同的属性(STATUSCOUNT),它们会冲突还是抛出并发修改异常?

最佳答案

正如Igor Artamonov所评论的,仅更改实体的一个属性仍然需要重写整个实体。考虑到这一点,您正在研究2个实体写入,必须在事务内部完成这些写入,以防止彼此覆盖。

如果与2a中排队的任务相关联的事务在提交2b事务之前开始,则您描述的流程将导致事务冲突。

2a任务的执行被延迟-这将是稍后您遇到的请求(实际延迟取决于当前应用的负载及其可扩展性配置)。它可能比2b执行要长得多。或者它可能很小,允许2a在2b结束之前开始。

我建议更改操作顺序,以使其更可预测,并且作为副作用,最大程度地减少事务冲突/重试的机会:


在当前请求线程上执行2b(在事务中)
在同一事务transactionally enqueue 2a任务中,该任务仅在2b成功之后才发生。否则,您需要注意在2b重试期间可能使多个2a任务入队。

09-05 08:40