10

「トランザクションの使用」の 2 番目の例を考えてみましょう (「名前付きキーでエンティティを更新するか、まだ存在しない場合は作成します」)。

https://developers.google.com/appengine/docs/java/datastore/transactions

ここで、このシナリオを考えてみましょう。マルチプレイヤー ゲームでは、任意の 2 人のプレイヤー間で 1 つの対戦のみが許可されます。これを確実にするために、各プレーヤーのキーを使用してキーが作成されます。このキーは、UniqueMatch エンティティのキ​​ーとして使用されます。

したがって、一致を作成するために、XG トランザクションが作成されます。このトランザクション内:

  1. そのキーを持つ UniqueMatch エンティティがまだ存在しないかどうかを確認します。そのキーを使用した datastore.get() 呼び出しが EntityNotFoundException をスローしない場合、これら 2 人のプレイヤー間の一致が既に存在することがわかっているため、rollback() してプレイヤーにエラー メッセージを表示します。

  2. 一致を作成するために配置する必要があるすべてのエンティティを put() します。これには、UniqueMatch エンティティと、その他のいくつかのエンティティが含まれます。

  3. その後、トランザクションがコミットされます。

これはうまくいくようです。ただし、短い時間枠内で任意の 2 人のプレイヤー間で 2 つのマッチを作成できることに気付きました。少しの間 (実際には、テストの 1 つで最大 10 ~ 20 秒)、datastore.get(key) への呼び出しで、そのキーが既に put() されているにもかかわらず、EntityNotFoundException がスローされます。

これは結果整合性のようです。しかし、キーによるエンティティの取得は、強い整合性が保証されているのではないでしょうか? この保証は、これが XG トランザクション内で行われるという事実によって影響を受けますか?

前もって感謝します、

4

1 に答える 1

1

あなたが見ている問題は、データストアが (キーまたはクエリによって)トランザクションの開始時にデータストアの状態のみを取得するためである可能性があると思います。

ドキュメントから(分離と一貫性の下で):

トランザクションでは、すべての読み取りが、トランザクション開始時のデータストアの現在の一貫した状態を反映します。これには、トランザクション内の以前のプットと削除は含まれません。トランザクション内のクエリと取得では、トランザクションの開始時点で、データストアの単一の一貫したスナップショットが表示されることが保証されています。

また、トランザクションの外では、コミットされたプットのみが表示されます ( docs ):

クエリまたは取得によってデータストアから取得されたエンティティには、コミットされたデータのみが表示されます。

考えられる解決策:

トランザクションの外部で UniqueMatch エンティティを作成します (appengine では同じキーを持つエンティティを配置できないため、同じキーを持つエンティティが既に存在する場合は例外がスローされます)。次に、トランザクション内で一致を作成するために必要な他のエンティティを作成/配置できます (必要な場合)。

最後に、UniqueMatch のキーを作成するときは、キーが常にプレーヤーと同じ順序で作成されるようにしてください。key(playerA,playerB)!=key(playerB,playerA)

于 2012-10-26T11:51:26.797 に答える