본문 바로가기
개발 지식/Backend

[Cache] Ehcache vs Caffeine Cache

by 에르주 2022. 9. 7.
반응형

서비스 플랫폼을 개발 운영하면서 가끔 사용자가 급작스럽게 늘어났을 때 DB Transaction Thread Dead Lock 또는 Collection Lock로 인하여 Exception이 터져 빨간 오류가 모니터링 페이지에 가득한 것을 볼 수 있습니다.

Local Cache와 Global Cache로 주로 쓰고 있는 Redis Cache로 나뉘어 소개하고(예정..?)

이번 장에서는 Local Cache의 Caffeine Cache와 Ehcache와의 차이점에 대해서 서술해보려고 합니다.

현재 통합API에서 쓰고 있는 local Cache는 ehcache 입니다. Ehcache는 in memory 캐시로써 빠르고 컴팩트하며 Hibernate 및 MyBatis에서 제공하는 기본 캐시입니다.

 

1) Ehcache

Ehcache는 직렬화된 데이터 객체를 저장하는 메모리 블럭입니다. 가장 널리 사용되는 Java 기반 캐시입니다. Ehcache는 프로세스 내 캐슁에서 테라바이트 크기의 캐쉬와 함께 프로세스 내/프로세스 외 혼합 구현으로 확장됩니다.

 

최신의 ehcache의 버전 3에서는 다음과 같이 개선사항이 있었습니다.

 

  1. javax.cache API (JSR-107)즉 JCache와 호환합니다.
    JCache는 java에서 제공하는 표준 Cashing API 입니다. Echache 내부적으로 JCache의 CachingProvider와 CacheManager 두개의 인터페이스를 구현하여 실행됩니다.
    (https://www.javadoc.io/doc/javax.cache/cache-api/1.0.0/javax/cache/package-summary.html)



  2. javax.cache 지원으로 즉시 사용할 수 있는 스프링 캐싱 및 최대 절전 모드 통합

  3. Offheap 전용 캐시를 포함하한 offHeap 스토리지 기능
    (https://www.ehcache.org/documentation/2.8/get-started/storage-options.html)

    Ehcache는 세가지 스토리지에 저장 할 수 있습니다.
    • 메모리 저장 공간 (in - Memory 저장)
    • OffHeap 공간 : Memory Heap 외부에 추가 유형의 메모리 저장소를 사용할 수 있도록 합니다. java GC가 적용되지 않는 offHeap 저장소이며 매우 큰 캐시를 생성 할 수 있습니다. (바이트 단위)
    • 디스크 공간 : File 캐시와 유사. 굳이 디스크 공간을 쓸 필요가 없으며 CacheManager를 이용하여 여러 디스크 저장소 경로를 구성 할 수 있습니다.

offheap

 

ehcache는 각각의 어플리케이션의 cache를 Terracotta Server를 활용하여 동기화 할 수 있습니다. 또한 JMX 모니터링 툴이 있어 캐시 사항을 모니터링 할 수 있습니다.

(https://www.ehcache.org/documentation/3.10/caching-concepts.html)

 

분산 처리 ehcache

 

 

2) Caffeine Cache


Caffeine Cache Github 페이지(https://github.com/ben-manes/caffeine) 에서 high performance 그리고 최적의 캐싱 라이브러리라고 소개하고 있습니다.

Google 오픈 소스 Guava Cache와 ConCurrentHashMap을 개선한 ConcurrentLinkedHashMap(https://github.com/ben-manes/concurrentlinkedhashmap)를 바탕으로 개선하였다고 한다.

또한 Ehcache와 마찬가지로 in-mermory를 활용하며 Java 8, Spring 4.3, Boot 1.4 이상에서 지원합니다.

 

이제 Caffeine Cache와 Ehcache에 대해 차이점을 살펴보려합니다.

 

3) Caffeine vs Ehcache

 

3-1) Ehcache

LRU(Least Recent Used), LFU (Least Frequency Used), FIFO(First In First Out) 세가지 제거 알고리즘을 제공합니다. 해당 알고리즘에 따라 메모리 공간이 가득차면 요소가 제거된다. 

 

3-2) Caffeine Cache

단순히 메모리 캐시 구성 요소를 사용하고 고성능 요구사항이 있는 경우 Caffeine은 우선 순위를 부여할 수 있으며 더 나은 캐시 제거 전략을 사용합니다.

Caffeine은 거의 최적의 적중률을 제공하는 Window TinyLfu 제거 정책을 사용합니다.

tinylfu

 

(https://dgraph.io/blog/refs/TinyLFU%20-%20A%20Highly%20Efficient%20Cache%20Admission%20Policy.pdf)

 

w-titnylfu

(https://www.sobyte.net/post/2022-04/caffeine/)

 

 

Window TintyLFu 정책에 대해 정리하자면 다음과 같습니다.

 

Main Cache안의 SLRU 정책의 Probation Cache, Protected Cache로 나뉘어져 있습니다. 공간의 80%에 자주 사용하는 데이터 Protected Cache에 할당하고 20% 자주 사용하지 않는 데이터는 Probation Cache에 저장합니다.

Protected Cache와 Probation Cache는 SLRU를 기반으로 합니다.

 

Protected Area는 제거 되지 않습니다. 반면에 probation area는 새로운 캐시 아이템이 들어올 때 probation area가 가득 찼다면 LRU rule에 의하여 제거되며 

 

Window Cache는 전체 cache size의 1% 정도이며 99%가 Main Cache 입니다. 

 

  • 새로운 데이터가 Cache에 쓰여질 때 첫번째로 쓰여지는 곳은 Window Cache이며 Window Cache 공간이 가득 찼을 때는 오래된 캐시가 Window 캐시 밖으로 제거됩니다. (LRU  방식)
  • Probation Cache 영역이 full이 아니면 이 데이터는 바로 Probation Cache 영역의 최근 엑세스 한 데이터 캐시 끝에 저장되며 Probation Cache 영역이 full일 경우에는 제거되거나 TinyLFU algorithm에 의하여 Probation Cache 영역에 쓰여집니다.
  • Probation Cache 영역 안의 캐시 데이터에 일정한 횟수 이상 접근 된다면, 그들은 Protected Cache 영역으로 승격되고  최근 엑세스 한 데이터 캐시 끝에 저장됩니다.. Protected Cache가 가득차면 가장 오래된 캐시 데이터가 밖으로 옮겨집니다. 이 때 오래된 캐시 데이터는 TinyLFU algorithm에 의해서 제거 되거나 Probation Cache 영역에 저장됩니다.

 

TinyLFU 제거 매커니즘

Window Cache 또는 Protected Cache로 부터 제거되는 캐시 데이터는 Candidate라고 불리고 Probation Cache에서 제거되는 캐시 데이터는 Victim이라 불립니다.

  • Candidate cache 접근 > Victim cache 접근 : Victim 데이터는 제거
  • Candidate cache 접근 < Victim cache 접근 && Candidate 접근 횟수 5번 이하: Candidate 데이터 제거
  • 둘 중 하나 랜덤하게 제거

 

 

Caffeine 캐시 내부 알고리즘은 LFU와 LRU의 장점을 통합했습니다. 서로 다른 캐시 영역에 서로 다른 특성을 가진 캐시 항목을 저장하면 최근에 생성된 캐시 데이터가 Window Cache로 들어가 제거 되지 않습니다.

자주 호출되는 캐시 아이템(LFU)은 Protected 영역에 들어가게 되며 이는 제거되지 않습니다.  캐시 공간이 가득차면 엑세스 빈도에 따라 Protected 영역의 캐시 항목이 유지되거나 제거됩니다.

호출 횟수와 호출 시간 두개의 차원이 잘 밸런스가 되어 있고 빈번히 호출되고 최근에 생성된 캐시 데이터들은 가능한 캐시에 유지 될 수가 있습니다.

전통적인 LRU LFU에서 처리 할 수 없는 잘 호출되지 않는 데이터 및 짧은 시간 단발성 트래픽을 더 잘 처리할 수 있게 되었습니다.

 

 

read / write

실무에서 Local Cache 방향성에 대해 고민하고 설계를 진행하고 있습니다. 특히 서버 API는 수많은 칼럼값이 있는 JSON Object 형태로 데이터를 조회 및 반환하고 있기 때문에 그 무엇보다 속도적인 측면에서 많은 고민들을 하고 있습니다.

이번에 스터디를 Caffeine Cache라는 것을 처음 알게 되었는데 Local Cache 방향성으로는 Caffeine Cache와 EhCache를 고려하고 있습니다.

더 나아가 Global Redis Cache와 적절한 캐시 전략으로 앞으로 좀 더 빠르고 정확한 데이터를 각 POC 프론트에 전달할 수 있는 방법을 찾아야 할 것 같습니다.

 

 

참고 사이트
https://gosunaina.medium.com/cache-redis-ehcache-or-caffeine-45b383ae85ee
https://github.com/ben-manes/caffeine/wiki/
https://www.ehcache.org/about/features.html
https://arxiv.org/pdf/1512.00727.pdf
https://www.sobyte.net/post/2022-04/caffeine
https://dgraph.io/blog/refs/TinyLFU%20-%20A%20Highly%20Efficient%20Cache%20Admission%20Policy.pdf

 

 

 

 

 

 

반응형

댓글