1

當使用Objectify嘗試加載給定類型的所有實體時,我遇到了不一致。當獲得給定類型的所有實體(本地雲端點)時,物化不一致性

我運行一個雲端點後端本地,並使用下面的方法來填充數據存儲的設置:

public static void dsUp() { 
    Store store1 = new Store("H&M", new GeoPt(new Float(56.157702), new Float(10.206938))); 
    Store store2 = new Store("Marc Jacobs", new GeoPt(new Float(56.158284), new Float(10.208618))); 
    Store store3 = new Store("Weekday", new GeoPt(new Float(56.158522), new Float(10.207547))); 

    ofy().save().entities(store1, store2, store3).now(); // Synchronous save to auto generate id 
} 

建立數據庫後,數據存儲查看器顯示三個對象創建:

Datastore Viewer after running dsUp() method

問題

我開始注意到,我的客戶端應用(iOS),有時只收到兩家店:

Received data at iOS client

我重新在後端我getStores()方法,並改變它,使它加載所有商店4次,記錄每次嘗試,並最終返回第一次嘗試的結果。

的方法(將其更改爲多個負載嘗試後),看起來是這樣的:

public static List<Store> getStores() { 

    List<Store> result = ofy().load().type(Store.class).list(); 
    LOGGER.warning("Getting Stores, try 1: " + result.toString()); 
    LOGGER.warning("Getting stores, try 2: " + ofy().load().type(Store.class).list()); 
    LOGGER.warning("Getting stores, try 3: " + ofy().load().type(Store.class).list()); 
    LOGGER.warning("Getting stores, try 4: " + ofy().load().type(Store.class).list()); 

    return result; // Returning the results from try 1 
} 

通常情況下,每一個試圖返回所有三家分店。但是,有時第一次嘗試,甚至第二次嘗試只會返回兩個商店。通過第三次和第四次嘗試,所有商店都被退回。

其中一個方法調用的記錄輸出如下所示。請注意,這次嘗試1和2只返回兩個商店。

Logged output from the local endpoints

我不能看到其存儲在數據庫重置之間留出任何圖案。有時它是一個,有時是另一個。然而,似乎在getStores()的同一調用中,如果嘗試1和2都失敗,它似乎缺少同一商店(如上圖所示)。

我試過了什麼?

我最初的想法是,我必須設置錯誤的Objectify過濾器。然而,據我所知,這似乎是有序的。在我的webapp/WEB-INF/web中。xml文件,我有以下的過濾器和過濾器映射:

<filter> 
    <filter-name>ObjectifyFilter</filter-name> 
    <filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>ObjectifyFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

我不是很熟悉物化的緩存,但我試過如下:

添加以下行作爲第一件事情我getStores()在後端方法,加載任何實體之前:

ofy().clear(); // Clear the cache 

我還加載實體在使用強一致性試過,如下:

List<Store> result = ofy().consistency(ReadPolicy.Consistency.STRONG).load().type(Store.class).list(); 

其他信息,可能是相關

我可以重新創建不一致,並且出現約1/5倍。但是,據我所知,它只發生在從頭開始設置數據庫後,使用前面提到的dsUp()方法。

嘗試之間,我用下面的方法來清除數據庫:

public static void dsDown() { 
    List<Key<Store>> allStoreKeys = ofy().load().type(Store.class).keys().list(); 
    ofy().delete().keys(allStoreKeys).now(); 
} 

至於數據存儲瀏覽器而言,dsDown()方法按預期工作,並保持數據庫空。據我所知,直接在Database Viewer中刪除實體可能會導致緩存未被刪除的問題。不過,我已經讀過,像在dsDown()方法中那樣使用Objectify刪除實體可以避免這個問題。

如果有任何其他信息我應該提供,請讓我知道。

謝謝!

EDIT(我的執行的解決方案,從@saiyr):

由於@saiyr指出,在本地運行時,這引起了不一致的數據存儲模擬最終一致性。以下屏幕截圖顯示了我如何將標誌添加到我的後端模塊的build.gradle文件中。

注:請注意,如果將模擬的最終一致性完全關閉(將標誌設置爲0)可能會導致Objectify事務出錯。這就是爲什麼我將標誌設置爲1的原因。有關詳細信息,請參閱this stack overflow post

你想的標誌添加到後端項目的build.gradle文件:

Backend module's build.gradle file

enter image description here

+1

這是否僅在將實體添加到數據存儲之後纔會發生? –

+0

@EricSimonton我只在使用dsUp()方法設置數據庫之後才測試過,而沒有花費太多時間。但是,我也通過設置數據庫來測試它,然後在嘗試獲取所有實體之前,從客戶端(iOS應用程序)創建實體。這導致了類似的不一致,看起來完全是隨機的,不管實體/實體是用dsUp()方法創建的還是從應用程序創建的。你認爲我應該在獲得實體之前通過測試嗎? – jonasjuss

回答

2

開發服務器數據存儲emulates eventual consistency。您將Objectify中的一致性設置爲STRONG是無效的,因爲您的can't enforce strong consistency on non-ancestor queries。對於dev服務器,您可以嘗試將datastore.default_high_rep_job_policy_unapplied_job_pct值設置爲零以解決此問題,但請注意,這僅影響本地開發。

+0

我已經更新了原來的帖子,並提供了我的解決方案的具體實現。我還在將標誌設置爲0時添加了有關Objectify事務可能存在的問題的信息。謝謝@saiyr! – jonasjuss

相關問題