1

使用Google App Engine的NDB數據存儲,如何確保在創建新實體後對實體列表進行高度一致的讀取?Google App Engine/NDB - 在投入之後非常一致地閱讀實體列表

示例用例是我擁有Employee類的實體。

  • 創建一個新員工的實體
  • 立即加載員工(包括已添加的一個)

我瞭解,該辦法之下將產生的列表的最終一致的讀取列表可能包含或不包含新員工的員工。這導致後者的糟糕體驗。

e = Employee(...) 
e.put() 
Employee.query().fetch(...) 

現在,這裏是我想過幾個選擇:

重要限定符

我只在乎讀誰補充新員工的用戶提供一致的清單。我不關心其他用戶是否有最終的一致性閱讀。

我們假設我不想讓所有員工置於祖先之下以啓用強一致的祖先查詢。在成千上萬的員工實體的情況下,5次寫入/秒限制是不值得的。

我們還假設我想要將寫入和列表讀取爲兩個單獨的HTTP請求的結果。理論上講,我可以將寫入和讀取放入單個事務(?)中,但這會成爲非RESTful API端點。

選項1

  • 在數據存儲上創建一個新員工實體
  • 此外,寫入新的員工對象內存緩存,本地瀏覽器的cookie,本地移動存儲。
  • 職工名單(最終一致)
  • 如果新員工的實體不在此名單查詢數據存儲,它從內存緩存/本地內存添加到列表(在我的應用程序代碼)
  • 渲染結果的用戶。如果用戶選擇新員工實體,則使用key.get()(強烈一致)檢索實體。

選項2

  • 使用事務職工名單
  • 查詢數據存儲在一個事務中

我不知道選擇2創建一個新員工實體實際上有效。

  • 從技術上講,在該實體的讀取事務發生之前,以前的寫入事務是否會寫入所有服務器?或者這是不正確的行爲?
  • 交易(包括XG)對實體組數量和員工名單(每個都是自己的實體組)都有一定限制,可能會超出此限制。
  • 只讀事務與正常讀取有什麼不同?

想法?選項#1似乎可行,但確保後續讀取的一致性似乎很多工作。

+0

你有新員工的關鍵,所以爲什麼要查詢。執行查詢並將實體添加到結果集中。另外,獲取密鑰將強制索引寫入。問題是在創建實體後多長時間才能執行查詢以及由誰執行?如果同一個用戶,那麼會話對象可以管理具有某種時間邊界的新創建實體的列表。我參與了一個擁有2000多個用戶的系統,我們通常不會看到CRUD操作的問題。 –

回答

0

我有同樣的問題,選項#2並沒有真正的工作:使用密鑰讀取將工作,但查詢可能仍然會錯過新員工。

選項#1可以工作,但只能在相同的請求。已保存的memcache密鑰隨時可能消失,但對另一個hw上可能運行的同一實例或另一個實例上的後續查詢仍會錯過新員工。

爲了一致的查詢結果而想到的唯一「解決方案」實際上並不是試圖強迫新員工進入結果,而是讓事情自然而然地流轉直到結果。我只是添加一個警告,即創建新用戶需要「一段時間」。如果可以容忍的話,可以在原始請求中保持輪詢/查詢,直到顯示出來爲止? - 這將是唯一確定員工創造活動的地方。

1

如果您不使用實體組,您可以爲實體一致性執行key_only查詢和get_multi(鍵)查找。對於新員工,您必須將新密鑰傳遞給get_multi的密鑰列表。

文檔:只有鍵的全局查詢與查找方法的組合將讀取最新的實體值。但是應該注意的是,只有鍵的全局查詢不能排除在查詢時索引不一致的可能性,這可能導致實體根本不被檢索。查詢的結果可能會基於過濾掉舊的索引值而生成。總之,只有在應用程序需求允許索引值在查詢時尚未一致時,開發人員纔可以使用僅鍵全局查詢,然後按鍵查找。

更多信息和魔法在這裏:Balancing Strong and Eventual Consistency with Google Cloud Datastore

0

這個問題是舊的,因爲我寫這篇文章。但是,這是一個很好的問題,並且會長期有效。

從原始問題選項#2將無法正常工作。

如果實體創建和後續查詢是真正獨立的,沒有上下文鏈接它們,那麼你實際上只是被卡住了 - 或者你不在乎。訣竅是幾乎總是有一些關係或一些必須被覆蓋的用例。換句話說,如果查詢確實是某種特定的查詢,那麼你真的不在意。在這種情況下,您只需引用CAP定理,並提醒客戶端執行查詢,這個系統的規模有多大。但是,幾乎總是如果您擔心最終的一致性,則需要處理一些用例或一組案例。例如,如果您有高分列表,則最高分必須位於列表的頂部。目前正在查看列表的用戶剛剛獲得了最高分數。另一個例子可能是,當創建員工時,該員工必須在「新員工」列表中。 所以你通常會利用這些已知的情況來平衡所需的吞吐量和一致性。例如,對於高分例子,您可能有能力保留高分的列表中的二級索引(實體)。你總是按鍵來獲取它,並且可以根據需要頻繁地寫入它,因爲高分不會經常產生。對於新員工示例,您可以使用通過將最後一名員工的時間戳存儲在內存緩存中而開始建議的方法。然後,當您查詢時,您會檢查並確保您的列表中包含該員工......或其他事項。

App Engine和類似系統的平衡寫入吞吐量和一致性的代價總是相同的。它需要增加模型複雜性/代碼複雜性來彌合業務需求。