위의 3가지 케이스는 전부 Local Cache로 관리되지만, 2nd level cache는 Local Cache, Remote Cache 두 방식으로 사용 가능하다.
여러 Application을 띄우고 로드벨런서를 앞에 두고 사용하는 경우, API Call 마다 각 Application에선 Entity를 각자 중복으로 조회하여 저장하는 형태이기 때문에, 각 Session 내부에서만 Cache를 공유하는 First Level Cache는 Hit율이 낮을 수 밖에 없다.
이 Cache를 클러스터링 하여 중앙에서 관리하는 것을 2nd Level Cache라고 한다.
방식은 Local Cache(IMDG) 방식과 Remote Cache 방식 2가지가 있다.
IMDG란?
IMDG 서비스 개념도
IMDG(In-Memory Data Grid)는 고가용성과 확장성을 제공하는 분산 메모리 시스템이다. 메모리를 주 데이터 저장소로 활용하기 위해서는 대용량 데이터 관리를 위한 신뢰성이 보장되어야 한다.
이를 위해 IMDG는 분산 클러스터 기술을 활용하고 있다. 다수의 컴퓨터 메모리를 그리드로 연결하여 하나의 큰 메모리 저장소를 구축한다. 서버를 동적으로 추가하여 용량을 증설할 수 있으며, 장애 시 자동복구를 위한 데이터가 여러 서버에 분산 관리된다.
IMDG(In-Memory Data Grid)는 다음과 같은 특징을 가진다.
다수의 컴퓨터 메모리(RAM)를 클러스터링 하여 하나의 큰 메모리 저장소로 구축
데이터 유실방지 및 복구를 위해 여러 서버에 데이터를 분산, 복제 관리
메모리(RAM) 클러스터의 수평적 확장이 가능하여 무제한 용량 지원
데이터는 객체 지향 및 비 관계형 데이터 모델로 관리
사용자의 데이터 요청은 다수의 컴퓨터에서 병렬로 처리
메모리(RAM) 외 디스크, DBMS 등의 저장소에서 데이터 영구 보관 가능
이름
구분
저장소
기타
Hazelcast
IMDG
In Memory
IMDG로 Invalidation Message Propagation 기능 제공
Infinispan
IMDG
In Memory
상동
Redis
NON-IMDG
In Memory
NON-IMDG로 Invalidation Message Propagation 기능 미제공
Ehcache
NON-IMDG
In Memory
상동
Ehcache + Terracotta
NON-IMDG
In Memory
Terracotta 서버 추가 구성으로 인한 부담
Local Cache + Hazelcast(IMDG)
사용방법
Local Cache (Near Cache)를 각 Application에 저장하며, Topic (queue)를 통해 수정된 데이터 정보를 주고 받으며 데이터 일관성을 유지하는 방식이다. 데이터를 Application에 적재하고 있으므로, Remote Cache 방식에서 발생하는 Network 지연은 발생하지 않아 가장 성능이 좋은 방식이다.
ITopic을 통해 데이터가 전송되므로 Hazelcast Management Center에선 Topic이 생성되는걸 확인할 수 있다.
Hazelcast Local Cache 방식은 적재된 데이터를 확인하는 방법이 따로 없는 듯 하다.
Hazelcast Management Center를 사용하여 Topic의 Publishes, Receives Count는 확인 가능하지만, 중요한 hit율이나 데이터 저장 정보 등 그 이상의 정보는 확인할 수 없었다.
(최신버전을 사용하면 데이터 조회, 히트율을 확인 가능하다는 제보가 있)
Remote Cache + Hazelcast
사용방법
일반적인 Remote Cache를 사용한 방식.
Hazelcast Remote Cache 방식도 마찬가지로 적재된 데이터를 확인하는 방법이 따로 없었다.
IMap을 통해 데이터가 전송되므로 Hazelcast Management Center에선 Map이 생성되는걸 확인할 수 있다.
하지만, Hazelcast Management Center를 사용하여 중요한 Hit율, 데이터 수, 메모리 사용량 등 중요한 정보를 확인할 수 있다.
성능은 Local Cache가 좋다고 하지만, Metric 성능은 Remote Cache 방식이 좋은 것을 확인할 수 있다.
@Query("firstname=James")
public List<Person> peoplewiththeirFirstNameIsJames();
@Query("firstname=%s")
public List<Person> peoplewiththeirFirstName(String firstName);
@Query("firstname=%s and lastname=%s")
public List<Person> peoplewithFirstAndLastName(String firstName,String lastName);