e-commerce 대용량 서버 프로젝트에서 세션 불일치 문제를 해결하기 위해 session storage방식으로 데이터를 관리하기로 정하였습니다. 이러한 In-memory DB인 Redis
와 Memchaced
중에서 세션 저장소로 어떤 것이 적합할지 비교해 보려고 합니다.
Memcached 자체에는 분산기능이 없지만 Memcached의 라이브러리인 Consistent Hashing
을 통해서 데이터를 분산합니다.
Consistent Hashing
을 이용하여 클라이언트가 DBMS에서 장애 시점을 읽어 다시 캐시하는 로직을 미리 만들어둘 수 있습니다.
위의 Memcached의 서비스 구조를 보면 알 수 있듯이, 클라이언트가 Memcached 서버의 주소를 모두 알고 있어 Memcached 서버 한 대가 장애가 발생하더라도 크게 문제가 발생하지 않습니다.
또한 Memcached는 해시 형태기 때문에 O(1)
의 성능을 내어 검색 시간이 매우 짧습니다.
만약 Consistent Hashing이 아니라면, 장애가 발생할 때 일반적으로 다른 프로그램에서는 남아있는 서버만큼만 트래픽을 보내기 위해 서버 설정을 다시 배포해야 합니다.
Memcached를 Master/Master 리플리케이션이 가능하도록 만든 Repcached
프로그램이 있어 메모리가 날라가도 원본 데이터로 즉시 복구할 수 있습니다.
다만, 전원이 내려가면 메모리의 내용이 모두 사라지는 메모리 캐시 서버는
주목적이 캐시이므로 내부 데이터가 사라져도 상관이 없을수도 있습니다.
Memcached의 메모리 할당 구조가 slab할당자
를 이용한 형태입니다. 때문에 메모리 재할당을 하지 않고 관리하는 형태를 취합니다.
Memcached는 작고 변하지 않는 정적인 데이터를 캐싱할 때 내부 메모리 관리가 Redis 만큼 복잡하지 않습니다. 때문에 Redis에 비해 능률적으로 이루어져 메모리 사용량이 낮습니다.
- 서버 한 대가 장애가 발생하더라도 큰 문제 없이 서비스를 제공할 수 있다.
- O(1)의 성능인 Memcached를 사용하면 통신 속도가 빠르다.
- Memcached에 저장한 원본 데이터는 메모리가 날라가도 즉시 복구할 수 있다.
- 트래픽이 몰려도 응답속도는 Redis에 비해 안정적이다.
- 데이터 변경이 적은 경우에 메모리 파편화 문제가 적은 편이다.
- 메모리 사용량이 Redis에 비해 낮다.
Redis는 Memcache와 비슷한 분산 캐시이며 저장소의 개념이 추가되었다고 생각하시면 됩니다. Memcached의 지지부진한 발전에 비해, Redis는 엄청난 속도로 발전하고 있습니다.
기능 | 특징 |
---|---|
Data Type | List, Sorted Set, Hash등의 자료구조를 제공. Collection 사용 가능. |
Replication | Master/Slave로 사용할 수 있는 리플리케이션을 제공. |
Persistence | RDB라는 현재 메모리의 Data Set에 대해서 Snapshot을 만들 수 있는 기능 제공. |
Pub/Sub | Redis를 Publisher/Subscribe 형태로 이용할 수 있는 기능 제공. |
Spring Data Redis에서는 SessionCallback 인터페이스를 통해 여려 명령을 동시에 처리하는 기능을 제공합니다.
또한, Spring Data Redis에서 기존의 데이터와의 호환성을 위해 Java 객체를 Redis에 저장할 때 Hash 자료구조 형태로 저장합니다.
스프링에서는 Spring data에서 제공하는 CrudRepository를 상속받아, Redis의 CRUD를 간단하게 처리할 수 있습니다.
데이터 복구 방식으로는 RDB
와 AOF
가 있는데,
RDB는 현재 메모리 상태의 snapshot을 만들어 사용하며
AOF는 로그에 남긴 Write/Update 이벤트를 기반으로 복구합니다.
RDB와 AOF는 결국엔 파일에 데이터를 기록하는 것이므로 성능을 저하시킵니다. 그래서 실제로 Master는 서비스만 하고 Slave에서 AOF와 RDB를 이용해서 백업하는 형태로 사용합니다.
Redis는 한 개의 KEY
에 저장할 수 있는 VALUE
의 범위가 512MB 입니다. Memcached는 1MB로 Redis에 비해 더 훨씬 작습니다.
싱글 스레드인 Redis는 snapshot을 뜰 때, 자식 프로세스를 하나 만들고 난 후 새로 변경된 메모리 페이지를 복사해서 사용합니다. 보통 Redis는 데이터의 변경이 잦을 때 사용하기 때문에 실제 메모리 양만큼 자식 프로세스가 복사하게 됩니다.
Redis는 jemalloc
을 이용하여 매번 malloc/free를 통해 메모리 할당이 이루어집니다. 결국 Redis에서 메모리 파편화가 발생하게 되어 할당 비용 때문에 응답 속도가 느려집니다.
다만, 이는 극단적으로 봤을 때 발생하는 일이며 치명적인 문제가 아니라고 합니다.
또한 jemalloc 4.x 버전부터 메모리 파편화를 줄이기 위한 jemalloc에 힌트를 주는 기능이 들어갔다고 합니다.
- Memcached에서 제공하지 않은 기능을 다양하게 제공한다.
- 해시 형태이기 때문에 Memcached와 성능 차이가 크지 않다.
- 리플리케이션이 가능하여 메모리가 날라가도 복구할 수 있다.
- Key에 저장할 수 있는 데이터의 범위가 Memcached에 비해 크다.
- 메모리를 2배로 사용하며, 메모리 파편화가 발생하기 쉽다.
- 트래픽이 몰리면 응답속도가 불안정한 편이다.
e-commerce 대용량 서버 프로젝트는 Spring을 사용하여 진행 중이기 때문에 여러 기능을 제공하는 Redis를 In-Memory DB로 선택하였습니다. 서비스의 세션 데이터를 저장하고 관리할 것이므로 자료형이 다양하고, 조작이 유리한 Redis가 편리할 것이라 판단하였습니다.
때문에 Redis의 단점들을 감수하며 Memcached에 비해 강력한 운영 기능을 가진 Redis
를 선택하게 되었습니다.