2012-05-01 74 views
2

這是關於GAE/Java的內存緩存一個非常普遍的問題:參照內存緩存對象和更新他們

我有被存儲在內存緩存稱爲網絡的對象,並且我有另一個對象調用用戶具有基準到網絡。

Network network=Memcache.get(networkKey); 
user._network=network; //user references an object that came from Memcache... 

我現在有一串代碼改變user._network(不接觸內存緩存):

user._network = //做一些改變的對象,而不觸及內存緩存

確定所以這裏的問題, 直接看代碼,最後一行是否更新了memcache中的網絡對象?我有需要訪問更新的網絡對象的servlet,問題是如果我錯在將Memcache對象視爲常規對象。

也許正確的方法是?

Network network=Memcache.get(networkKey); 
network.doUpdate(); 
Memcache.put(key,network); 
+0

最後一行不會執行任何操作,除非您的Memcache類以某種方式知道網絡對象的密鑰是什麼。 Memcache需要密鑰,價值。 –

+0

對不起,我解決了這個問題,這不僅僅是一個錯字。問題仍然存在...... –

+0

明白了,請參閱下面的答案。 –

回答

4

您提供的後一個代碼示例是更新memcache中網絡對象的正確方法,但是它的工作方式與您期望的方式不同。

您的用戶對象是指從memcache中檢索到的網絡對象的實例。每次從memcache中檢索對象時,都會得到不同的實例。而且,由於實例與緩存中的原始實例邏輯上不同,只要更新緩存值,那些實例就會與緩存版本不同步。

例如:

Network network=Memcache.get(networkKey); 
Network networkTwo = Memcache.get(networkKey); 
user._network=network; 
networkTwo.doUpdate(); 
// network and networkTwo are now different 
Memcache.put(networkKey,networkTwo); 
// user._network still refers to the initial instance of network, not networkTwo 

如果你希望你的用戶對象總是指網絡版的是內存緩存中你需要在你的代碼的其他邏輯。

+0

謝謝丹。因此,只是爲了得出結論(如果我錯了,隨時糾正我),對Memcached對象的引用將不會保存更新的值,它們將只在創建對它的引用時保存Memcached對象。所以如果一個程序員想要處理和更新Memcached對象,那麼引用是無用的(因爲引用的很大一部分是他們跟蹤對象的變化,這在這裏不會發生)。 –

+0

需要明確的是,您實際上沒有對memcache內的對象的引用,您可以通過讀取memcache創建一個對象實例的引用。如果更新存儲在內存緩存中的對象,那些更改將不會自動反映到任何現有實例中。所以你的最後一點基本上是正確的,你從memcache讀取的對象的引用不足以滿足你的目的。 –

0

該代碼確實更新了內存緩存中的網絡對象,但對已在該網絡實例上具有句柄的應用程序其他部分中的對象的引用未更新。 Memcache存儲SERIALIZED對象。

在GAE中使用memcache的最佳方式是與Objectify一起使用,用於緩存數據存儲對象和存儲大量生成昂貴對象的對象。它不適合存儲頻繁更改的對象或應用程序中許多其他對象使用的對象。