我有一个要求,我们正在从数据库加载静态数据,以便在
Java应用程序中使用.任何缓存机制应具有以下功能:
>从数据库加载所有静态数据(一旦加载,此数据将不会更改)
>从数据库加载新数据(启动时数据库中显示的数据不会改变,但可以添加新数据)
所有数据的延迟加载不是一个选择,因为应用程序将部署到多个地理位置,并且必须与单个数据库进行通信.懒惰加载数据将使特定元素的第一个请求太慢,其中应用程序位于数据库的不同区域.
我在Guava中一直使用MapMaker API,但是我们现在正在升级到最新版本,我似乎找不到与CacheBuilder API相同的功能;我似乎找不到在启动时加载所有数据的干净方式.
一种方法是从数据库加载所有密钥,并通过缓存单独加载它们.这将工作,但会导致N 1调用数据库,这是不是很有效的解决方案我正在寻找.
public void loadData(){
List 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();
}
}
任何人都可以想到更好地解决我的两个要求?
功能要求
我不认为预加载缓存是一个不寻常的要求,所以如果CacheBuilder提供了一个配置选项来预加载高速缓存,那将是很好的.我认为提供一个接口(很像CacheLoader)将在启动时填充缓存将是一个理想的解决方案,如:
CacheBuilder.newBuilder().populate(new CachePopulator(){
@Override
public Map populate() throws Exception {
return getAllElements();
}
}).build(new CacheLoader(){
@Override
public Element load(String key) throws Exception {
return getElement(key);
}
});
该实现将允许使用所有相关的Element对象预先填充Cache,同时保持底层的CustomConcurrentHashMap对外界不可见.