簡體   English   中英

多對多的App Engine JDO交易

[英]App Engine JDO Transaction on multiple many-to-one

我有一個簡單的領域模型,如下所示

驅動程序-鍵(字符串),運行計數,唯一軌道計數

曲目-關鍵(字符串),運行次數,唯一驅動程序次數,最佳時間

運行-鍵(?),驅動程序鍵,跟蹤鍵,時間,布爾驅動程序更新,布爾跟蹤更新

我需要能夠在同一事務中更新運行和驅動程序; 以及同一筆交易中的“運行”和“跟蹤”(顯然是為了確保我不會兩次更新統計信息,或者錯過增量計數器)

現在,我嘗試分配作為運行密鑰,該密鑰由驅動程序密鑰/跟蹤密鑰/運行密鑰(字符串)組成

這使我可以在一個事務中更新Run實體和Driver實體。

但是,如果我嘗試一起更新“運行”和“跟蹤”實體,它將抱怨它無法在多個組上進行交易。 它說它在交易中同時擁有駕駛員和卡車,並且不能同時在兩者上操作...

tx.begin();

run = pmf.getObjectById(Run.class, runKey);
track = pmf.getObjectById(Track.class, trackKey);
//This is where it fails;

incrementCounters();
updateUpdatedFlags();
tx.commit();

當我做類似的事情來更新運行和驅動程序時,這足夠奇怪了。

關於我還可以如何映射域模型以實現相同功能的任何建議?

使用Google App Engine時, 所有數據存儲區操作都必須位於同一實體組中的實體上 這是因為您的數據通常存儲在多個表中,而Google App Engine無法在多個表中進行事務。

擁有一對一和一對多關系的實體自動位於同一實體組中 因此,如果一個實體包含對另一個實體或實體集合的引用,則可以在同一事務中對兩者進行讀取或寫入。 對於沒有所有者關系的實體,您可以創建具有顯式實體組父級的實體。

您可以將所有對象放在同一個實體組中,但是如果有太多用戶試圖同時修改實體組中的對象,則可能會引起爭用。 如果每個對象都在其自己的實體組中,那么您將無法進行任何有意義的事務。 您想在兩者之間做些事情。

一種解決方案是在同一實體組中具有跟蹤和運行。 您可以通過讓Track包含運行列表來完成此操作(如果執行此操作,則Track可能不需要運行計數,唯一驅動程序計數和最佳時間;可以在需要時進行計算)。 如果你不想跟蹤有運行的列表,你可以使用一個無主的一個一對多的關系 ,並指定運行的實體組父是它的軌道(請參閱“創建實體的實體組”對本頁面 )。 無論哪種方式,如果運行與它的跟蹤位於同一實體組中,則可以執行涉及運行及其部分/全部跟蹤的事務。

對於許多大型系統,通過使用冪等操作來完成更改,而不是使用事務來保持一致性。 例如,如果Driver和Run不在同一個實體組中,則可以通過以下方式更新Driver的運行計數:首先執行查詢以獲取過去某個日期之前所有運行的計數,然后在事務中,用新的計數和上次計算的日期更新驅動程序。

使用日期時請記住,機器可能會有某種時鍾漂移,這就是我建議過去使用日期的原因。

我想我找到了一個橫向但仍然干凈的解決方案,這對我的領域模型仍然有意義。

域模型的變化如下:

驅動程序-鍵(string-id),驅動程序狀態-例如 id =“ Michael”,運行次數= 17

跟蹤-鍵(字符串ID),跟蹤統計-例如 id =“ Monza”,bestTime = 157

RunData-鍵(string-id),統計數據-例如 id =“ Michael-Monza-20101010”,時間= 148

TrackRun-鍵(Track / string-id),track-stats-updated-例如。 id =“ Monza / Michael-Monza-20101010”,track-stats-updated = false

DriverRun-鍵(驅動程序/字符串ID),驅動程序狀態已更新-例如。 id =“ Michael / Michael-Monza-20101010”,driver-stats-updated = true

現在,我可以立即或在自己的時間內用運行中的統計信息自動(即精確地)更新跟蹤的統計信息。 (與“驅動程序/運行”統計信息相同)。

因此,基本上,我必須以一種非常規的關系方式來擴展我對問題建模的方式。 你怎么看?

意識到這已經晚了,但是..

您是否看到過這種銀行帳戶轉帳方法? http://blog.notdot.net/2009/9/Distributed-Transactions-on-App-Engine

在我看來,您可以通過將增量計數器分成兩個步驟作為IncrementEntity並進行處理,然后在交易失敗后再取走碎片,來做類似的事情。

從博客:

  1. 在交易中,從支付帳戶中扣除所需的金額,然后創建一個轉賬子實體進行記錄,在“目標”字段中指定接收帳戶,現在將“其他”字段留空。
  2. 在第二筆交易中,將所需的金額添加到接收帳戶,並創建一個轉帳子實體進行記錄,在“目標”字段中指定支付帳戶,並在步驟1中的“其他”字段中創建轉帳實體。
  3. 最后,更新在步驟1中創建的Transfer實體,將“其他”字段設置為我們在步驟2中創建的Transfer。

該博客提供了Python中的代碼示例,但應該易於適應

關於這個主題,有一個有趣的google io會話http://www.google.com/events/io/2010/sessions/high-throughput-data-pipelines-appengine.html

我猜您可以更新“運行”統計信息,然后執行兩項任務來分別更新“驅動程序”和“軌道”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM