Java 응용 프로그램에서 사용할 정적 데이터를 데이터베이스에서로드해야하는 경우가 있습니다. 시작 -에 데이터베이스 (데이터베이스에 존재하는 데이터로부터 데이터베이스에서 모든 정적 데이터 (한 번로드는,이 데이터가 변경되지 않습니다)Guava 캐시에 대한 사전로드 값
- 로드
- 로드 새로운 데이터 : 모든 캐싱 메커니즘은 다음과 같은 기능을 가지고 있어야 변경 사항은 변경되지 않지만 새 데이터를 추가 할 수 있음)
응용 프로그램이 여러 지리적 위치에 배포되고 단일 데이터베이스와 통신해야하므로 모든 데이터의 지연로드가 옵션이 아닙니다. 데이터를 게으르게로드하면 응용 프로그램이 데이터베이스와 다른 영역에있는 경우 특정 요소에 대한 첫 번째 요청이 너무 느려집니다.
Guava에서 MapMaker API를 성공적으로 사용해 왔지만 현재 최신 버전으로 업그레이드하고 있으며 CacheBuilder API에서 동일한 기능을 찾을 수 없습니다. 시작시 모든 데이터를로드하는 깨끗한 방법을 찾지 못하는 것 같습니다.
한 가지 방법은 데이터베이스에서 모든 키를로드하고 캐시를 통해 키를 개별적으로로드하는 것입니다. 이것은 작동하지만 데이터베이스에 대한 N + 1 호출을 발생시킬 수 있습니다. 이는 내가 찾고있는 효율적인 솔루션이 아닙니다.
또는 다른 해결책은 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 캐시를 미리로드 할 수있는 구성 옵션을 제공하면 좋을 것입니다 .
CacheBuilder.newBuilder().populate(new CachePopulator<String, Element>(){
@Override
public Map<String, Element> populate() throws Exception {
return getAllElements();
}
}).build(new CacheLoader<String, Element>(){
@Override
public Element load(String key) throws Exception {
return getElement(key);
}
});
이 구현은 캐시가 모든 관련 요소가 미리 입력되어있을 수 있습니다 것 : 나는 같은 이상적인 솔루션이 될 것입니다 시작시 캐시를 채 웁니다 (많은 CacheLoader 같은) 인터페이스를 제공 생각 기본 CustomConcurrentHashMap을 외부 세계에 보이지 않게 유지합니다.
구아바 문제 목록에 기능 요청을 추가하십시오. –
추가됨 (문제 775) – Richard
http://code.google.com/p/guava-libraries/issues/detail?id=775 –