我使用番石榴的理想缓存 [英] my ideal cache using guava

查看:135
本文介绍了我使用番石榴的理想缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

过去几周我一直在尝试使用guava的 MapMaker 。请参阅前两个问题此处在其中遵循我的思维过程。

Off and on for the past few weeks I've been trying to find my ideal cache implementation using guava's MapMaker. See my previous two questions here and here to follow my thought process.

根据我所学到的,我的下一次尝试将放弃软值,转而支持maximumSize和expireAfterAccess:

Taking what I've learned, my next attempt is going to ditch soft values in favor of maximumSize and expireAfterAccess:

ConcurrentMap<String, MyObject> cache = new MapMaker()
        .maximumSize(MAXIMUM_SIZE)
        .expireAfterAccess(MINUTES_TO_EXPIRY, TimeUnit.MINUTES)
        .makeComputingMap(loadFunction);

其中

Function<String, MyObject> loadFunction = new Function<String, MyObject>() {
   @Override
   public MyObject apply(String uidKey) {
      return getFromDataBase(uidKey);
   }
};

然而,我仍在努力解决的另一个问题是,这个实现将驱逐对象,即使一旦他们的时间到了,他们就很容易到达。这可能会导致多个对象在环境中浮动相同的UID,这是我不想要的(我相信我想要达到的目标称为规范化)。

However, the one remaining issue I'm still grappling with is that this implementation will evict objects even if they are strongly reachable, once their time is up. This could result in multiple objects with the same UID floating around in the environment, which I don't want (I believe what I'm trying to achieve is known as canonicalization).

据我所知,唯一的答案是有一个额外的地图作为一个内部工具,我可以检查数据对象是否仍然在内存中:

So as far as I can tell the only answer is to have an additional map which functions as an interner that I can check to see if a data object is still in memory:

ConcurrentMap<String, MyObject> interner = new MapMaker()
        .weakValues()
        .makeMap();

并且会修改加载函数:

Function<String, MyObject> loadFunction = new Function<String, MyObject>() {
   @Override
   public MyObject apply(String uidKey) {
      MyObject dataObject = interner.get(uidKey);
      if (dataObject == null) {
         dataObject = getFromDataBase(uidKey);
         interner.put(uidKey, dataObject);
      }
      return dataObject;
   }
};

然而,使用两个映射而不是一个缓存似乎效率低下。有没有更复杂的方法来解决这个问题?一般来说,我是以正确的方式解决这个问题,还是应该重新考虑我的缓存策略?

However, using two maps instead of one for the cache seems inefficient. Is there a more sophisticated way to approach this? In general, am I going about this the right way, or should I rethink my caching strategy?

推荐答案

两张地图是否有效完全取决于getFromDatabase()的价格,以及对象的大小。做这样的事情似乎并不合理。

Whether two maps is efficient depends entirely on how expensive getFromDatabase() is, and how big your objects are. It does not seem out of all reasonable boundaries to do something like this.

至于实现,看起来你可能会以稍微不同的方式对你的地图进行分层。得到你想要的行为,并且仍然具有良好的并发属性。

As for the implementation, It looks like you can probably layer your maps in a slightly different way to get the behavior you want, and still have good concurrency properties.


  1. 使用弱值创建第一个地图,并将计算函数getFromDatabase(在这张地图上。

  2. 第二张地图是即将到期的,也是计算的,但这个函数只是从第一张地图获得。

通过第二张地图进行所有访问。

Do all your access through the second map.

换句话说,到期地图用于固定最近使用的地图内存中对象的子集,而弱引用映射是真正的缓存。

In other words, the expiring map acts to pin a most-recently-used subset of your objects in memory, while the weak-reference map is the real cache.

-dg

这篇关于我使用番石榴的理想缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆