如何防止多次同时加载非缓存值?

Dan*_*lor 7 java performance caching

如何以有效的方式同时防止多次同时加载缓存中不存在的值?

典型的缓存使用情况是以下伪代码:

Object get(Object key) {
 Object value = cache.get(key);
 if (value == null) {
  value = loadFromService(key);
  cache.set(key,value);
 }
 return value;
}
Run Code Online (Sandbox Code Playgroud)

问题:在从服务(数据库,WebService,RemoteEJB或其他任何东西)加载值之前,可能会在同一时间进行第二次调用,这将使值再次加载.

例如,当我为用户X缓存所有项目,并且经常查看该用户并且具有许多项目时,很可能同时调用其所有项目的负载,导致服务器上的负载过重.

我可以使get函数同步,但这会迫使其他搜索等待,没有多大意义.我可以为每个密钥创建新的锁,但我不知道在Java中管理如此大量的锁是否是个好主意(这部分是特定于语言的,我将其标记为的原因java).

或者我可以使用另一种方法?如果是这样,最有效的是什么?

Pet*_*rey 7

你可以做的一般事情就是使用Object的hashCode.

您可以拥有一个基于hashCode使用的锁数组,以减少冲突的可能性.或者作为一个黑客,您可以使用自动装箱字节始终返回相同对象的事实.

Object get(Object key) {
    Object value = cache.get(key);
    if (value == null) {
        // every possible Byte is cached by the JLS.
        Byte b = Byte.valueOf((byte) key.hashCode());
        synchronized (b) {
            value = cache.get(key);
            if (value == null) {
                value = loadFromService(key);
                cache.set(key, value);
            }
        }
    }
    return value;
}
Run Code Online (Sandbox Code Playgroud)

  • 哇,我绝不会以这种方式使用字节! (2认同)

min*_*das 3

不要重新发明轮子,使用番石榴LoadingCache记忆供应商

如果您使用 Ehcache,请阅读read-through,这就是您要求的模式。您必须实现CacheEntryFactory接口来指示缓存如何在缓存未命中时读取对象,并且必须使用 的Ehcache实例包装该实例SelfPopulatingCache