我有一个要求,我们从数据库加载静态数据以在 Java 应用程序中使用。任何缓存机制都应该具有以下功能:
- 从数据库加载所有静态数据(一旦加载,这些数据就不会改变)
- 从数据库加载新数据(启动时数据库中存在的数据不会改变,但可以添加新数据)
延迟加载所有数据不是一种选择,因为应用程序将部署到多个地理位置并且必须与单个数据库进行通信。当应用程序位于与数据库不同的区域时,延迟加载数据将使对特定元素的第一个请求太慢。
我一直在 Guava 中成功使用 MapMaker API,但我们现在正在升级到最新版本,我似乎无法在 CacheBuilder API 中找到相同的功能;我似乎无法找到一种在启动时加载所有数据的干净方法。
一种方法是从数据库加载所有密钥并通过缓存单独加载这些密钥。这可以工作,但会导致对数据库的 N+1 次调用,这并不是我正在寻找的有效解决方案。
public void loadData(){
List<String> keys = getAllKeys();
for(String s : keys)
cache.get(s);
}
或者另一个解决方案是使用 ConcurrentHashMap 实现并自己处理所有线程和丢失的条目?我并不热衷于这样做,因为 MapMaker 和 CacheBuilder API 免费提供基于密钥的线程锁定,而无需提供额外的测试。我也非常确定 MapMaker/CacheBuilder 实现将具有一些我不知道/没有时间研究的效率。
public Element get(String key){
Lock lock = getObjectLock(key);
lock.lock();
try{
Element ret = map.get(key)
if(ret == null){
ret = getElement(key); // database call
map.put(key, e);
}
return ret;
}finally {
lock.unlock();
}
}
谁能想到更好的解决方案来满足我的两个要求?
功能要求
在短期内我只会使用Cache.asMap().putAll(Map<K, V>)
.
Guava 11.0 发布后您可以使用Cache.getAll(Iterable<K>) http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/cache/Cache.html#getAll(java.lang.Iterable),这将为所有缺失的元素发出单个批量请求。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)