지금까지 S/W 개발하면서 경험했던 캐시(Cache)들 소개

안녕하세요, 하마연구소입니다.

컴퓨팅에서 캐시(Cache)는 데이터에 빠르게 접근하기 위한 레이어로 데이터 로딩이 지연되거나 병목이 예상되는 앞단에 위치합니다.
CPU와 메모리 사이에 있는 L1, L2, L3 캐시나 빠른 I/O 처리를 위하여 스토리지(HDD, SSD 등)에도 사용됩니다.

H/W뿐만 아니라 S/W에서도 자주 사용되며 적절한 캐시 설계에 따라 성능을 극대화할 수 있습니다.
보통 어플리케이션과 영구저장소 또는 다른 어플리케이션 사이에 위치합니다.




요즘은 분산 클러스터링 환경에서 편리성과 훌륭한 속도를 내는 Memcached나 Redis를 많이 사용하며, 언젠가부터는 Memcached도 캐시 설계할 때 도입 대상에서 제외되는 추세로 보입니다.
왠만하면 Redis 사용합니다.

제가 지금까지 경험했던 캐시 솔루션을 정리해 보려고 합니다.
보통 Java 기반으로 어플리케이션을 작성하였기에 그에 맞는 캐시를 많이 경험한 점 참고하시기 바랍니다.


1. 로컬캐시

Ehcache

Java 기반 어플리케이션 개발하면 가장 쉽게 접하는 캐시입니다.
어렵지 않은 설정으로 다양한 캐시 기능을 사용할 수 있으며, 역사도 꽤 길기에 믿고 사용하면 됩니다.
다양한 기능으로는 영속성을 보장하기 위한다면 캐시 데이터 디스크 저장할 수 있으며, 어플리케이션의 여러 프로세스들 간에 공유하여 분산 캐시를 구성할 수도 있습니다.

단, 캐시 기능에 더이상 새로운 기능을 넣을께 없어서 그런지 라이브러리 업데이트가 활발하지는 않습니다.





Caffeine

2010년대 중후반 부터 Spring Boot에서는 기본 캐시 라이브러리를 Ehcache에서 Caffeine으로 변경하였습니다.
아마 Spring Boot 버전 2부터였던 것으로 기억합니다.
Ehcache가 제공하는 기능이 많아지고 그만큼 무거워졌기 때문에 로컬 캐시라는 본연 기능에 충실하고자 심플한 카페인 캐시 라이브러리가 각광 받았습니다.
또한 스프링에서 아주아주 간단한 설정만으로 쉽게 캐시를 적용할 수 있습니다.
그리고 군더더기 없는 소스코드 때문에 성능도 매우 띄어나다고 합니다.

다만 다양한 캐시 expire 전략과 TTL 설정을 하려면 소스코드 단에서 커스터마이징이 필요했습니다.





ExpiringMap

이걸 캐시라고 하기에는 무리가 따르지만, 빠르게 데이터에 접근하기 위한 용도로 도입했으니 캐시라고 봐도 괜찮을 듯 합니다.

ExpiringMap 라이브러리의 주요 기능은 일정시간이 지나면 Map 인스턴스 내의 Entry 데이터를 메모리에서 릴리즈될 수 있도록 합니다.
이와 관련하여 이전에 글을 작성한 것이 있으니 참고하시기 바랍니다.

캐시가 그닥 필요하지 않기에 어플리케이션에 별도 캐시를 도입하지 않았지만 일부 로직에 캐시 기능이 필요하거나, 도입했어도 특별한 목적으로 이 ExpiringMap을 사용하면 유용합니다.
예를들어 어플리케이션 전체적으로 동일한 exire TTL을 설정하여 Caffeine을 적용하였지만, 일부 로직에서만 다른 TTL이 필요할 경우에 아주 쉽고 가독성 높은 소스코드로 작성할 수 있습니다.




2. 클러스터링 캐시

Hazelcast

헤젤케스트(헤이즐케스트)는 제가 직접 도입한 것은 아니며, 도입된 상태를 경험하였습니다.
2010년대 초반 당시 여러 노드에서 어플리케이션 프로세스가 운영되는 환경에서 순수 로컬 캐시인 Ehcahe를 사용하고 있었는데, 한 노드에서 캐시 데이터가 업데이트되면 다른 노드에는 실시간으로 반영되지 않는 문제점이 발생하였습니다.
독립적인 로컬 캐시에서는 당연한 상황이지만, 해당 서비스가 다소 민감한 내용을 다루는 것이기에 사용자에게는 캐시 업데이트로 인한 순간적인 데이터 불일치가 용납될 수 없었습니다.

따라서 대안을 찾던 중에 여러 노드에서 캐시 데이터의 atomic을 보장해주는 Hazelcast를 도입하였습니다.
클러스터링 환경에서 캐시 데이터를 일치시킨다는 표면적인 기능은 매우 좋아 보였습니다.
일반적으로 평온한 트래픽 상황에서는 우리의 목적을 만족하였습니다.
하지만 대량 트래픽과 빈번한 캐시 데이터 업데이트가 발생하면 지들끼리 데이터 일치시키느라 엄청난 네트워크 비용이 발생하여 어플리케이션이 종종 죽었습니다.
당시에 파티녀닝 기능이 있었는지 또 그것을 활성화 했는지 정확하지 않지만, 아마도 각 노드에는 모두 동일한 전체 캐시 데이터를 유지했던 것으로 기억합니다.





3. 분산 캐시

Redis

현존하는 캐시 중에 단연 최고라고 할 수 있는 레디스입니다.
가장 빠른 성능일지, 가장 적은 운영비용일지, 가장 안전한 시스템일지는 보장할 수 없지만,
꽤 많은 많은 레퍼런스나 노하우, 꽤 심플하지만 왠만한 기능을 다 있고, 꽤 편리한 운영환경 등등...
믿고 사용할 수 있는 캐시 솔루션입니다.
Spring 환경은 물론이고 수많은 언어에서도 쉽게 사용할 수 있습니다.

In-memory 캐시뿐만 아니라 디스크에도 저장할 수 있기에 영속성 있는 데이터 처리에도 뛰어난 성능을 제공합니다.
그리고 스트림이나 이벤트 처리에도 사용하는 등 매우 다양한 목적으로 사용하고 있습니다.

단점은 찾아보면 부족한 부분이 있겠지만, 굳이 단점을 찾지 않아도 될만큼 대체품이 없다면 그냥 믿고 사용하면 됩니다.





4. DB캐시(?)

MySQL MEMORY 엔진

과거 2010년 경에 매우 특별한 목적으로 MySQL의 MEMORY 엔진을 사용했었습니다.
MySQL은 기본적으로 InnoDB 엔진이며, 이는 디스크에 데이터를 저장하여 I/O 작업에 병목과 지연을 발생시킵니다.

반면에 MEMORY 엔진은 말그대로 메모리에만 데이터를 저장합니다.
따라서 매우 빠른 I/O 처리가 가능하지만 DB가 재시작되면 데이터 유지가 안되는 특징이 있습니다.
딱 캐시용도로 사용하기에 적합하죠.

가장 큰 특징은 SQL을 사용하여 데이터를 쿼리할 수 있다는 것입니다.
단순한 key-value 데이터가 아닌 RDB 형태의 데이터를 저장하고 다양한 필터링으로 쿼리할 수 있습니다.

지금은 동일한 기능은 아니지만 Redis 등 더욱 막강한 솔루션이 있으니 굳이 단순 캐시 용도로 사용할 필요는 없지만, DBMS에 JOIN 쿼리 시에 빠른 성능을 위하여 MEMORY 엔진 테이블을 구성하는 용도는 생각해 볼 수 있겠습니다.






5. 2중 캐시

로컬캐시+분산캐시

매우 빠른 데이터 접근과 데이터의 atomic을 위하여 로컬캐시와 분산캐시를 동시 적용한 경험이 있습니다.
HA나 클러스터링 환경의 Redis에 접근하기 위해서는 네트워크를 통해야 하며, 이는 매우 큰 비용입니다.
이 네트워크 처리 속도를 줄이려면 어쩔 수 없이 로컬캐시를 사용해야 합니다.
하지만 로컬캐시를 사용하면 여러 노드들 간의 데이터 불일치가 발생하고요.
TTL을 짧게 가져가면 데이터 불일치는 최소화할 수 있지만, 매우 빈번한 expire로 cache miss가 자주 발생하고 그만큼 hit율을 떨어지니 캐시 본연의 기능을 할 수 없습니다.

따라서 이를 해결하고자 로컬캐시와 분산캐시를 혼합하였습니다.
CPU와 메모리 사이의 L1과 L2 캐시처럼 어플리케이션과 DB 사이의 1차 캐시와 2차 캐시를 둔 것이지요.

처리 흐름은 다음과 같습니다.
  1. 사용자의 요청이 들어오면 그 트래픽을 받은 해당 어플리케이션의 로컬 캐시에서 데이터를 찾습니다.
  2. Cache miss이면 Redis에서 데이터를 찾습니다.
  3. 그래도 cache miss이면 DB에서 원하는 데이터를 얻어오고 이를 Redis와 로컬캐시에도 저장합니다.
이렇게 구성하려면 어플리케이션 설정과 소스코드가 다소 복잡합니다.
로컬캐시와 Redis에서 모두 cache miss가 발생하면 오히려 성능이 떨어지기도 할겁니다.
로컬캐시와 Redis의 expire 전략과 TTL 값을 서로 다르게 조절하는 등 섬세한 튜닝이 필요합니다.




이밖에도 매우 다양한 캐시 솔루션이 존재합니다.
구성하려는 시스템 특성과 프로젝트 상황에 따라 그 솔루션을 도입하면 됩니다만, 현재로서 왠만한 상황에서는 Redis면 충분할 듯 합니다.
조금이라도 빨라야 하는 요구사항이라면 Memcached 도입을 고려해보면 좋고요.

추후에는 캐시가 필요 없을만큼 네트워크와 디스크 I/O 작업이 빨라질까요?
글쎄요, 그만큼 CPU 속도도 빨라지니 캐시는 계속 존재할 것으로 생각됩니다.

이상 제가 경험해봤던 몇가지 캐시 솔루션을 정리해 보았습니다.
감사합니다.

댓글

Popular Posts

AI 시대, SEO가 아닌 GEO에 포커싱해야 하는 이유

AI 메모리 HBM 외에 HBF도 주목

네이버 쇼핑 잘 나가네요, 구팡이 절대 강자인줄~