다른 프로세스가 데이터베이스를 수정하면 최대 절전 모드 2 레벨 캐시 무효화
-
05-07-2019 - |
문제
데이터베이스 히트를 피하기 위해 Hibernate의 2 단계 캐싱을 사용하는 응용 프로그램이 있습니다.
MySQL 관리자와 같은 외부 프로세스가 데이터베이스 수정 (업데이트/삽입/삭제)을 직접 연결할 때 Java Application의 최대 절전 모드 2 레벨 캐시를 무효화하는 쉬운 방법이 있는지 궁금했습니다 (업데이트/삽입/삭제).
우리는 사용 중입니다 ehcache 우리의 두 번째 레벨 캐시 구현으로.
우리는 @cache (usage = cacheconcurrencystrategy.read_write)와 @cache (usage = cacheconcurrencystrategy.nactomprict_read_write)의 혼합을 사용하며 각 엔터티에서 타임 스탬프를 사용하여 낙관적 동의 컨트롤을 활성화하지 않습니다.
SessionFactory에는 2 단계 캐시를 관리하는 방법이 포함되어 있습니다. 캐시 관리
sessionFactory.evict(Cat.class, catId); //evict a particular Cat
sessionFactory.evict(Cat.class); //evict all Cats
sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections
그러나 우리는 @cache로 개별 엔티티 클래스에 주석을 달기 때문에 "확실하게"(예 : 수동 단계 없음)를 목록에 추가 할 수있는 중심 위치는 없습니다.
// Easy to forget to update this to properly evict the class
public static final Class[] cachedEntityClasses = {Cat.class, Dog.class, Monkey.class}
public void clear2ndLevelCache() {
SessionFactory sessionFactory = ... //Retrieve SessionFactory
for (Class entityClass : cachedEntityClasses) {
sessionFactory.evict(entityClass);
}
}
Hibernate의 2 단계 캐시가 엔티티 (캐시가 당신을 보호하는 것)를 쿼리하지 않는 한 DB에서 엔티티가 변경되었음을 알 수있는 실제 방법은 없습니다. 따라서 솔루션으로서 우리는 단순히 두 번째 레벨 캐시가 모든 것을 퇴거 시키도록 강요하는 방법을 호출 할 수 있습니다 (다시 잠금 및 동시성 제어로 인해 "읽기"또는 오래된 데이터를 업데이트 할 위험이 있습니다).
해결책
기반 chssply76 주석 다음은 2 레벨 캐시에서 모든 엔티티를 발표하는 방법입니다 (JMX 또는 기타 관리자 도구를 통해이 방법을 관리자에게 노출시킬 수 있음).
/**
* Evicts all second level cache hibernate entites. This is generally only
* needed when an external application modifies the game databaase.
*/
public void evict2ndLevelCache() {
try {
Map<String, ClassMetadata> classesMetadata = sessionFactory.getAllClassMetadata();
for (String entityName : classesMetadata.keySet()) {
logger.info("Evicting Entity from 2nd level cache: " + entityName);
sessionFactory.evictEntity(entityName);
}
} catch (Exception e) {
logger.logp(Level.SEVERE, "SessionController", "evict2ndLevelCache", "Error evicting 2nd level hibernate cache entities: ", e);
}
}
다른 팁
SessionFactory 많은 것이 있습니다 evict()
그 목적을 위해 정확하게 방법 :
sessionFactory.evict(MyEntity.class); // remove all MyEntity instances
sessionFactory.evict(MyEntity.class, new Long(1)); // remove a particular MyEntity instances
최대 절전 모드와 JPA는 이제 기본 2 레벨 캐시에 직접 액세스 할 수 있습니다.
sessionFactory.getCache().evict(..);
entityManager.getCache().evict(..)
나는 모든 최대 절전 모드 캐시를 무효화하는 방법을 찾고 있었고이 유용한 스 니펫을 발견했습니다.
sessionFactory.getCache().evictQueryRegions();
sessionFactory.getCache().evictDefaultQueryRegion();
sessionFactory.getCache().evictCollectionRegions();
sessionFactory.getCache().evictEntityRegions();
다른 사람에게 도움이되기를 바랍니다.
당신은 이것을 시도 할 수 있습니다 :
private EntityManager em;
public void clear2ndLevelHibernateCache() {
Session s = (Session) em.getDelegate();
SessionFactory sf = s.getSessionFactory();
sf.getCache().evictQueryRegions();
sf.getCache().evictDefaultQueryRegion();
sf.getCache().evictCollectionRegions();
sf.getCache().evictEntityRegions();
return;
}
도움이되기를 바랍니다.
분산 된 캐시를 사용할 때 고려해야 할 한 가지는 QueryCache가 로컬이며 한 노드에서이를 퇴치한다고해서 다른 노드로부터 퇴거하지 않는다는 것입니다. 또 다른 문제는 쿼리 캐시에서 날짜를 검색하려고 할 때 쿼리 영역을 퇴치하지 않고 엔티티 영역을 퇴치하면 N+1 선택이 발생합니다. 이 주제에 대한 좋은 독서 여기.