我正在使用 Java 风格的 Google Appengine,并且我正在尝试执行以下操作:
1 - 创建一个属性 COUNT 为 0 的实体。
2a - 启动执行一些网络调用的任务队列任务,并更新同一实体的 STATUS 属性(使用 Datastore#put
)
2b - 同时,在原始“线程”中,为 COUNT 保存一个不同的数字。 (也使用Datastore#put
)
鉴于 2a
和 2b
可能在同一时刻并行完成,但它们更新两个不同的属性(STATUS
和 >COUNT
),这些是否会发生冲突或像并发修改异常一样抛出?
最佳答案
正如 Igor Artamonov 所评论的那样,仅更改实体的一个属性仍然需要重写整个实体。考虑到这一点,您将看到两个实体写入,这两个实体写入必须在事务内部完成,以防止相互覆盖。
如果与 2a 中排队的任务关联的事务在提交 2b 事务之前启动,您描述的流程将导致事务冲突。
2a 任务执行被延迟 - 它将是一个稍后到达您的应用程序的请求(实际延迟取决于您的应用程序当前的负载及其可扩展性配置)。它可能比 2b 执行长很多。或者它可以很小,允许 2a 在 2b 结束之前开始。
我建议更改操作的顺序,使其更具可预测性,并且作为副作用,最大限度地减少事务冲突/重试的机会:
- 在当前请求线程上执行 2b(在事务中)
- 在同一笔交易中transactionally enqueue 2a 任务,只有在 2b 成功后才会发生。否则,您需要注意在 2b 重试期间可能会排队多个 2a 任务。
关于java - 并发写入 GAE 数据存储实体的不同属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41565980/