的谷歌App Engine文檔包含了這一段:GAE交易失敗和冪等
注意:如果您的應用程序提交一個 事務,當接收到一個例外,它並不總是意味着該交易失敗。 可能會收到DatastoreTimeoutException, ConcurrentModificationException或DatastoreFailureException 在事務已提交併且最終將成功應用 的情況下發生異常。只要有可能,使您的 數據存儲交易idempotent,以便如果您重複交易, 最終結果將是相同的。
等等,什麼?看起來有一類非常重要的事務,它們根本不可能變成冪等因爲它們依賴於當前的數據存儲狀態。例如,一個簡單的計數器,就像一個像按鈕一樣。交易需要讀取當前計數,增加它,並再次寫出計數。如果交易似乎「失敗」,但並不真正失敗,並且我無法在客戶端上說出這一點,那麼我需要再試一次,這將導致一次點擊生成兩個「喜歡」。 GAE有什麼方法可以防止這種情況發生?
編輯:
看來,這是在分佈式系統中固有的問題,按照比吉多·範羅蘇姆非其它 - 請參見以下鏈接:
app engine datastore transaction exception
所以看起來設計冪等如果你想要高度的可靠性,交易是非常必要的。
我想知道是否可以在整個應用程序中實現一個全局系統來確保冪等性。關鍵將是維護數據存儲中的事務日誌。客戶端會生成一個GUID,然後在請求中包含該GUID(對於同一個請求,重試時將重新發送相同的GUID)。在服務器上,在每個事務開始時,它將在數據存儲中查找具有該ID的Transactions實體組中的記錄。如果它找到了,那麼這是一個重複的事務,所以它會在沒有做任何事情的情況下返回。
當然,這需要啓用跨組交易,或將單獨的事務日誌作爲每個實體組的子項。如果失敗的實體密鑰查找速度很慢,性能也會受到影響,因爲幾乎每個事務都會包含失敗的查找,因爲大多數GUID都是新的。
就附加數據存儲交互而言額外的$成本而言,如果我必須使每個交易都是冪等的,這可能仍然會少一些,因爲這將需要大量檢查每個級別數據存儲中的內容。
閱讀Nick Johnsons關於分佈式交易的文章 - http://blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine –
這非常有趣。我正在考慮如何將該技術應用於創建可靠計數器的任務。如果只有一個用戶訪問該計數器就足夠簡單了:假設客戶端知道計數器的當前值,那麼只需將計數器的預期下一個值發送到數據庫,而不是發送消息「增加」。然而,我碰到的絆腳石是:如果多個用戶可能(可能同時)增加計數器,你將如何實現這一點。似乎應該有一種不涉及保存日誌的方式。 – eeeeaaii
在數據存儲中有很多有關計數器的討論,如果您有很多併發的高頻更新,您會發現需要使用分片計數器才能獲得吞吐量。 –