2012-05-01 24 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一起使用,用于缓存数据存储对象和存储大量生成昂贵对象的对象。它不适合存储频繁更改的对象或应用程序中许多其他对象使用的对象。