10

考慮的用途「交易」的第二個例子(「與名爲關鍵,如果它不存在更新實體,或創建」):GAE HDR:實體通過關鍵字檢索最終在XG交易中是否一致?

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

現在考慮這種情況。多人遊戲只允許任何兩個玩家之間進行單一比賽。爲了確保這一點,使用每個玩家的密鑰創建一個密鑰。該密鑰用作UniqueMatch實體的密鑰。

所以爲了創建一個匹配,創建了一個XG事務。在此次交易中:

  1. 我們檢查是否已經沒有使用該密鑰的UniqueMatch實體。如果使用該鍵的datastore.get()調用不會拋出EntityNotFoundException,那麼我們知道這兩個玩家之間的匹配已經存在,所以我們回滾()並向玩家顯示錯誤消息。

  2. 我們把()我們需要放置的所有實體爲了創建匹配。這包括UniqueMatch實體以及一些其他幾個實體。

  3. 然後交易被提交。

這似乎工作正常。不過,我注意到我可以在短時間窗口內創建兩個球員之間的兩場比賽。對於一段時間(其中一次測試中最多10-20s),我調用datastore.get(key)會拋出EntityNotFoundException,即使該鍵已經被put()。

這似乎是最終的一致性。但是不是實體回收由關鍵保證是強烈一致的?這種擔保是否受XG交易中的這一事實影響?

由於提前,

+0

這可能是一個類似的問題,球員們創造了UniqueMatch該鍵時確保。我在評論中看錯了,請參閱Guido的評論。 http://stackoverflow.com/questions/12367904/write-read-with-high-replication-datastore-ndb/12368444我也確信,一旦你有一個密鑰從.put你可以隨時檢索項目,但它似乎並非如此。也許是Memcache。 –

+0

嗯,我不太確定,Guido專門討論查詢,而不是通過密鑰實體檢索。對於查詢,我希望最終的一致性(實際上已經正確記錄)。 Memcache可能是一種選擇,是的。如果我找不到更好的方法,我會研究memcache,謝謝。 – fnf

+0

當然,你確實提到了鍵的實體,所以我想我會鏈接那個討論。我會高興你的問題。 –

回答

1

我想你看到的可能是因爲數據存儲得到(通過按鍵或查詢)的問題,只看到在交易的開始數據存儲的狀態。

docs(下隔離性和一致性):

在一個事務中,所有讀取在事務開始時反映數據存儲的當前,一致的狀態。這不包括交易中的先前的放入和刪除。在事務內部進行查詢和保證會在事務開始時看到數據存儲的單個一致快照。

此外,事務之外,你將只能看到已提交(docs)看跌期權:通過查詢從數據庫中檢索

實體或獲取只會看到提交的數據。

一個可能的解決方案:

創建UniqueMatch實體的事務之外(AppEngine上不會讓你把一個實體使用相同的密鑰,所以它會如果實體拋出一個異常使用相同的密鑰已經存在)。然後,您可以創建/放置在事務內部創建匹配所需的其他實體(如果需要的話)。

最後,創建他們密鑰總是以相同的順序,因爲key(playerA,playerB)!=key(playerB,playerA)