Chapter 1. Local Cache & Invalidation Message Propagation 전략 도입 배경
- 쿠폰 메타데이터의 엔티티를 조회하는 비율이 굉장히 높았다.
- 자주 변경되지 않는 성격을 갖고 있었기에 캐시에 적합했다.
- 세션 내부에서 캐시를 공유하는 First Level Cache의 Hit율은 낮았다. 반면 여러 세션에서 캐시를 공유하면 Second Level Cache가 적용되면 좋지 않을까? 라는 생각
- First Level Cache는 하나의 요청 내에서 생성되는 세션별로 사용되는 캐시다.
- 이 중 로컬 캐시와 리모트 캐시 중 어떤게 더 나을까?
- 성능은 당연히 로컬 캐시
- 일관성은 리모트 캐시
- 시스템의 엔티티 사용 패턴은 기존에는 1초에 수백에서 수천번의 조회가 있었다. 따라서 매번 네트워크를 타는 리모트보단 로컬이 적합하다고 생각했다.
- 로컬 캐시는 일관성을 보장할 수 없으니까
- 따라서 Local Cache With IMDG를 통해 성능과 일관성을 잡을 수 있었다.
Chapter 2. Hibernate Cache 동시성 전략과 구현체의 선택
- Cache Concurrency Starategy는 아래 4가지가 존재했다.
- Read-only : 엔티티가 수정이 가능하기 때문에 부적합
- Nonstrict read: 엔티티에 동시 수정이 빈번하지 않으면서 조회가 많기 때문에 적합
- Read/Write: 엔티티 수정이 빈번하지 않고, 스펙상 제공하는 락으로 인한 성능 저하로 부적합
- Transactional: JTA를 통한 트랜잭션때문에 부적합
- Invalidation Message Propagation 기능을 제공하는 IMDG 기반 Cache 구현체가 필요했다.
Chapter 3. Hazelcast 그리고 Second Level Cache
- 배포 방식은 Embedded, Client-Server Mode를 제공한다.
- 임베디드는 Java API와 캐시 노드가 동일한 JVM에 들어간다.
- 클라이언트-서버 모드는 각기 캐시 서버에 접근해서 노드를 추가해줘야하는 부분이 있다.
- AWS Cloud Discovery를 통해 클러스터링을 진행했다. 흐름은 아래와 같다.
- 애플리케이션 실행
- AWS에서 제공하는 API를 호출
- AWS Instance에 등록한 태그로 필터링
- 인스턴스 N개의 메타 정보 수신 후 클러스터링
- Hazelcast의 데이터 적재 방식은 분산 적재와 로컬 적재를 제공한다.
- 분산 배포의 경우 데이터가 분산되어 저장되기 때문에 조회 시 네트워크 오버헤드가 존재한다.
- 또한 엔티티를 수정한 이 후 롤링 업데이트나 블루 그린 배포 시에 역직렬화 이슈가 존재한다.
- 캐싱된 엔티티가 수정됐을 때 타 서버에 전파를 위해 Hazelcast Distributed Event를 사용한다.
- 인스턴스 간의 캐시 무효화 메시지가 도착했을 때 시간 차이로 인한 신뢰성 문제가 없어야 한다.
Chapter 4. Cache Hit율 극대화 전략
- 캐시에 있으면 캐시에서, 없다면 모아서 데이터베이스에서 모아서 한꺼번에 반환하기
결론
- 조회가 매우 빈번한 테이블에 대해서 엔티티만 캐싱하라
- GC 부담을 최소화하기 위해서 힙 사이즈를 적절하게 설정하고 캐시 엔트리 사이즈도 조절하여 메모리 가용성을 보장해야 한다.