Redis는 2009년에 Salvatore Sanfilippo가 만든 원격 디렉터리 서버(REmote DIctionary Server)의 약자입니다. 반면에 멤캐시드는 2003년에 Brad Fitzpatrick이 만든 메모리 캐시 서버 제품입니다. 오늘은 데이터 캐시 제품중 가장 인기있는 이 두 제품에 대해서 다음과 같은 목차로 비교해 보겠습니다.
Table Of Contents
Redis와 Memcached 공통점
Redis와 Memcached는 모두 다음과 같은 특징을 가지고 있습니다.
- NoSQL 인메모리 데이터 구조
- C로 작성
- 오픈 소스
- 애플리케이션 속도 및 성능을 높이는 데 사용
- 밀리초( millisecond ) 미만의 지연 시간 (latency)
오늘 포스팅에서는 애플리케이션에서 두 가지 중 어떤 것을 사용할지 현명하게 선택할 수 있도록 Redis와 Memcached를 최신의 상세한 비교 정보를 제공합니다.
문서
가장 먼저 확인할 수 있는 것은 Redis는 Memcached보다 훨씬 더 다양한 문서가 존재합니다. 추가로 최근에는 AI 챗봇도 홈페이지에서 공식 지원되어 질문에 바로바로 답을 받을 수 있습니다. 따라서 개발자나 관리자가 학습, 관리, 사용이 더 쉽습니다.
다만, 기본적으로 Memcached는 단순성을 위해 설계되었기 때문에 복잡하지 않습니다. 반면 Redis는 광범위한 사용 사례에 효과적인 풍부한 기능을 제공하지만 알아야 할 것들이 많습니다.
데이터베이스 모델 (Database Model)
Redis는 주로 키-값 저장소입니다. 키는 이진 문자열이지만, 값은 이진 문자열로만 제한되지 않는다는 것이 Redis의 장점입니다. 키는 복잡한 객체를 저장하고 이에 대한 다양한 연산을 제공하는 다양한 데이터 구조가 될 수 있습니다. 또한 Redis는 Redis 모듈을 통해 확장성을 제공합니다. Redis 모듈은 핵심 기능 세트에서 사용할 수 없는 추가 데이터 구조와 기능을 제공하는 확장 기능입니다. 다음은 추가적인 모듈로 사용할 수 있는 몇 가지 기능의 샘플입니다.
- Document Store (문서 저장소)
- Graph DBMS (그래프 DBMS)
- Search Engine (검색 엔진)
- 시계열 DBMS
반면, 멤캐시드는 이진 문자열만 값으로 지원하는 일반 키-값 저장소입니다.
데이터 구조( Data Structure )
위에서 언급했듯이 Redis는 문자열, 해시, 목록, 집합, 정렬된 집합, 비트맵, 비트필드, HyperLogLog, 지리적 공간 인덱스, 스트림 등 매우 유연하게 사용할 수 있는 여러 데이터 구조 유형을 제공합니다. 이에 대한 자세한 내용은 핵심 데이터 구조 유형별 주요 Redis 사용 사례 문서에서 확인할 수 있습니다.
DB-Rank의 인기도
데이터베이스의 인기가 높아질수록 더 많은 사용자 커뮤니티, 더 많은 토론과 사용자 생성 튜토리얼, 배포 최적화에 도움이 되는 DBaaS 플랫폼 및 분석 도구와 같은 타사 도구를 통해 더 많은 도움과 지원을 받을 수 있습니다.
Redis는 단순성, 풍부한 데이터 구조, 훌륭한 문서로 인해 DB-Engines에 따르면 2024년 4월 현재 전 세계에서 8번째로 인기 있는 데이터베이스입니다. Memcached는 현재 28번째로 가장 인기 있는 데이터베이스입니다.
키-값 데이터베이스 모델을 기준으로 Redis와 Memcached의 순위를 매기면, Redis가 1위, Memcached가 4위를 차지합니다. 그러나 오픈 소스 키-값 데이터베이스 또는 온프레미스에 배포할 수 있는 데이터베이스만 찾는 경우에는 Amazon DynamoDB와 Microsoft Azure Cosmos DB가 모두 클라우드에서만 배포할 수 있는 상용 데이터베이스이기 때문에 Memcached가 2위에 올랐습니다.
아키텍처
Redis와 Memcached는 모두 클라이언트-서버 아키텍처를 따릅니다. 클라이언트는 키-값 형태로 서버에 데이터를 채웁니다.
Redis는 싱글 스레드인 반면, 멤캐시드는 멀티스레드 아키텍처를 사용합니다. 멤캐시드는 컴퓨팅 용량이 확장되면 더 많은 작업을 처리할 수 있는 코어가 있는 시스템에서 더 잘 확장됩니다. 다만, 레디스가 추가 코어를 활용하기 위해 동일한 시스템에서 둘 이상의 Redis 인스턴스를 시작해서 확장할 수 있습니다. 하지만, 코어에 따라 레디스를 늘리는 것은 관리자나 개발자에게 부담을 줄 수 있습니다.
사용 편의성
앞의 데이터베이스 모델 섹션에서 설명한 것처럼, 다중 모델 데이터베이스인 Redis는 모든 유형의 데이터 모델과 함께 사용할 수 있습니다. Redis에서는 복잡한 작업을 단순화하기 때문에 코드를 쉽게 작성할 수 있습니다. Redis에는 고급 데이터 구조가 있으며 단순한 문자열 값에만 국한되지 않습니다. 예를 들어, 애플리케이션에서 데이터를 Sets으로 저장하고 List에서 Sets을 추적하려는 경우 Redis에서 쉽게 이 작업을 수행할 수 있습니다. Memcached에서는 이와 유사한 작업이 d어렵습니다. 결국 개발자가 더 많은 라인을 작성해야합니다.
멤캐시드는 일반 문자열 값만 저장합니다. 따라서 데이터 구조의 복잡성은 애플리케이션이 처리해야 합니다.
데이터 파티셔닝
Redis와 Memcached는 여러 노드 인스턴스에 걸쳐 데이터 파티셔닝을 지원합니다.
파티셔닝 방법은 Redis와 Memcached가 각각 다릅니다.
Redis
레디스는 표준 해싱 정책에서 tag를 지원하고 정규 표현식을 이용한 사용자 정의 해싱을 지원하여 사용자에게 더 많은 옵션을 제공합니다.
- 표준 해싱 정책
- 16383 해싱 슬롯을 이용한 해싱 기법 사용 (consistent hashing 사용안함)
- "we simply take the CRC16 of the key modulo 16384."
- 키의 일부를 사용하여 해싱하는 해싱 tag 지원
- 사용자 정의 해싱 정책
- PCRE(Perl 호환 정규 표현식) 를 이용한 사용자 정의 해싱 정책을 지원합니다.
Memcached
멤캐시드의 분산 정책에서 트래픽 부하가 균등하게 분산되도록 하기 위해 일관된 해싱(consistent hashing)이 권장하는 접근 방식입니다.
- 일반 해싱 정책
- 일반 해싱정책은 노드 변경시 많은 데이터 이동을 유발할 수 있어 추천하지 않음.
- 일관된 해싱 정책 ( consistent hashing )
- 일반적으로 원형 공간(원 형태의 해시 공간)을 사용하여 노드와 데이터를 배치하여 노드가 변경되어도 재배치가 적게 일어납니다.
지원 언어
Redis는 고급 언어부터 저수준 언어까지 가장 많이 사용되는 거의 모든 프로그래밍 언어를 지원합니다. 하지만 멤캐시드는 Redis에 비해 지원 언어 수는 적지만 모든 인기 언어를 지원합니다.
No | Memcached | Redis |
1 | .Net | C |
2 | C | C# |
3 | C++ | C++ |
4 | ColdFusion | Clojure |
5 | Erlang | Crystal |
6 | Java | D |
7 | Lisp | Dart |
8 | Lua | Elixir |
9 | OCaml | Erlang |
10 | Perl | Fancy |
11 | PHP | Go |
12 | Python | Haskell |
13 | Ruby | Haxe |
14 | Java | |
15 | JavaScript (Node.js) | |
16 | Lisp | |
17 | Lua | |
18 | MatLab | |
19 | Objective-C | |
20 | OCaml | |
21 | Pascal | |
22 | Perl | |
23 | PHP | |
24 | Prolog | |
25 | Pure Data | |
26 | Python | |
27 | R | |
28 | Rebol | |
29 | Ruby | |
30 | Rust | |
31 | Scala | |
32 | Scheme | |
33 | Smalltalk | |
34 | Swift | |
35 | Tcl | |
36 | Visual Basic |
트랜잭션
Redis '트랜잭션'은 아래 세 가지 보증을 통해 실행됩니다:
- 트랜잭션은 직렬화되어 순차적으로 실행됩니다.
- 모든 명령이 처리되거나 또는 아무 명령도 처리되지 않습니다(원자 트랜잭션).
- check-and-set을 사용한 Optimistic lock(낙관적 잠금) 제공
Redis는 한 클라이언트 시스템에서 한 번에 하나의 명령만 실행되도록 합니다. 트랜잭션의 모든 명령은 원자성을 보장하기 위해 "EXEC" 명령이 호출될 때 실행됩니다.
반면 멤캐시드는 트랜잭션 관리를 제공하지 않습니다.
복제
Redis는 마스터 인스턴스의 정확한 복사본을 생성하는 간단한 리더-팔로워(마스터-슬레이브) 복제를 제공하며, 다음과 같은 기능을 제공합니다.
- 마스터는 슬레이브가 연결되어 있는 한 데이터 명령을 계속 슬레이브에 보냅니다.
- 연결이 끊어지면 슬레이브는 연결이 끊어지는 동안 놓친 데이터만 복사하는 부분 재동기화를 따릅니다.
- 부분 재동기화가 불가능하면 전체 재동기화를 시도합니다.
- 고급 장애 조치 보호를 위해 고가용성 기능을 활용할 수도 있습니다.
기본 Memcached는 복제를 지원하지 않지만, 무료 오픈 소스 패치인 Repcached를 사용하여 배포에 고가용성을 달성할 수 있습니다. 이 패치는 멀티마스터 복제 및 비동기 데이터 복제를 제공하며, 모든 Memcached 명령을 지원합니다.
스냅샷/지속성 ( Snapshot / Persistence )
스냅샷은 단순히 특정 시점의 데이터베이스에 대한 읽기 전용 뷰(read-only view)입니다. Redis는 스냅샷을 지원하며, 기본적으로 데이터 세트의 스냅샷을 dump.rdb라는 바이너리 파일에 디스크에 저장합니다. 수동으로 스냅샷을 호출하거나, 빈도를 사용자 지정하거나, 작업 실행을 위한 임계값을 변경할 수 있습니다.
지속성은 SSD(솔리드 스테이트 디스크)와 같은 내구성 있는 스토리지에 데이터를 기록하는 것을 말합니다. Redis는 다양한 지속성 옵션을 제공합니다.
다음은 Redis가 지원하는 지속성 옵션입니다.
- RDB(Redis Database): RDB 지속성은 지정된 간격으로 데이터 세트의 특정 시점 스냅샷(point-in-time snapshots)을 수행합니다.
- AOF(Append Only File): AOF 지속성은 서버가 수신하는 모든 쓰기 작업을 기록합니다. 그런 다음 서버 시작 시 이러한 작업을 다시 재생하여 원래 데이터세트를 재구성할 수 있습니다. 명령은 Redis 프로토콜 자체와 동일한 형식을 사용하여 기록됩니다. 이 방법은 모든 명령이 다시 실행되므로 더 많은 공간을 차지하며, 스냅샷의 내구성이 떨어지는 방법입니다.
- No persistence(지속성 없음): 지속성을 완전히 비활성화할 수 있습니다. 이 옵션은 캐싱할 때 사용되기도 합니다.
- RDB + AOF: 동일한 인스턴스에서 AOF와 RDB를 모두 결합할 수도 있습니다.
반면 멤캐시드는 지속성( on-disk persistence )을 지원하지 않습니다.
확장성
Redis
Redis는 데이터베이스를 수평적으로 확장하는 두 가지 기술이 있습니다:
- Redis 클러스터에 샤드 추가하기
- Redis HA(마스터/레플리카) 설정에 노드 추가하기
더 많은 메모리 또는 컴퓨팅이 필요한 경우 Redis 설정을 수직적으로 확장할 수도 있습니다. HA 설정이 있거나 Redis 클러스터 기술을 사용하는 경우 다운타임 없이 이 작업을 수행할 수 있습니다.
Memcached
멤캐시드 서버는 노드 간에 데이터를 분산하는 메커니즘(샤딩)을 제공하지 않습니다. 따라서 멤캐시드에서 수평적 확장성은 노드를 더 추가하는 것만큼 간단하며, 데이터를 여러 개의 샤드로 분할하는 문제는 애플리케이션/클라이언트 수준에서 수행해야 합니다.
이를 도와줄 수 있는 오픈 소스 도구가 몇 가지 있습니다.
통신 프로토콜
Redis는 네트워크 프로토콜로 TCP를 사용하며 UDP는 지원하지 않습니다.
멤캐시드는 TCP와 UDP 통신 프로토콜을 모두 지원합니다.
지원되는 캐시 관리(cache replacement) 정책
Redis는 다양한 유형의 캐시 관리 정책을 지원합니다. 아래는 Redis에서 지원하는 정책들중 일부 입니다.
- noeviction: "noeviction"에서는 메모리가 바운드에 도달하면 에러가 반환됩니다.
- allkeys-lru: Lru는 "가장 최근에 사용한 것"을 의미합니다. 이 정책은 가장 최근에 사용된 데이터를 제거합니다.
- allkeys-lfu: Lfu는 "가장 덜 자주 사용됨"을 의미합니다. 이 정책은 사용 빈도가 가장 낮은 데이터를 제거합니다.
- allkeys-random: 이 정책은 데이터를 무작위로 제거합니다.
- volatile-lru: 휘발성 데이터는 만료 데이터 세트와 함께 있습니다. 이 정책은 가장 최근에 사용된 휘발성 데이터를 제거합니다.
- volatile-lfu: 휘발성 데이터가 만료 데이터 세트와 함께 있습니다. 이 정책은 사용 빈도가 가장 낮은 휘발성 데이터를 제거합니다.
- volatile-random: 이 정책은 휘발성 데이터를 무작위로 제거합니다.
- volatile-ttl: "TTL"은 유효 기간을 의미합니다. 이 정책은 수명이 가장 짧은 데이터를 제거합니다.
멤캐시드는 공간이 필요할 때 LRU 알고리즘을 사용하여 데이터를 제거합니다. 먼저 이미 만료된 데이터를 검색하여 삭제할 데이터를 찾고 만료된 데이터를 사용할 수 없는 경우 LRU 알고리즘을 사용합니다.
Publish & Subscribe Messaging (게시 및 구독 메시징)
Redis는 게시/구독 메시징(게시 및 구독)을 지원합니다. 이를 위해 사용되는 세 가지 명령이 있습니다.
클라이언트는 구독(subscribe)을 사용합니다.
구독
구독 취소
구독 및 구독 취소는 특정 채널에서 메시지를 받는 데 사용됩니다.
서버에서는 게시(publish)를 사용합니다.
게시
'게시'는 클라이언트에 데이터를 푸시하는 데 사용됩니다.
멤캐시드는 게시 및 구독 메시징(Pub/Sub messaging)을 지원하지 않습니다.
스트림 지원
Redis는 5.0 이상 버전에서 새로운 데이터 구조인 "Redis 스트림"을 사용하여 Kafka와 유사한 스트림을 지원합니다. Redis Streams는 클라이언트 애플리케이션이 분산된 방식으로 메시지를 소비할 수 있도록 하는 Apache Kafka와 같은 소비자 그룹 개념이 있어 확장 및 고가용성 시스템을 쉽게 만들 수 있습니다.
멤캐시드는 스트림에 대한 기본 지원을 제공하지 않지만, 짧은 지연 시간으로 스트림 처리를 위한 Kafcache와 같은 오픈 소스 라이브러리 도구가 있습니다.
Geospatial, 지리 정보 지원
Redis에는 위치의 경도 및 위도 데이터를 저장하는 지리 공간 인덱스( Geospatial indexes )라는 데이터 구조가 있습니다. 두 지점 사이의 거리를 계산하거나 가까운 장소를 찾는 등 지리공간 데이터에 대해 다양한 작업을 수행할 수 있습니다.
Memcached에는 지리공간 데이터를 처리하기 위한 특별한 데이터 구조가 없습니다.
성능(Performance)
인메모리 키-값 데이터 저장소 간의 성능 비교는 비용 절감 수단으로 관심을 가질 만한 규모로 시스템을 배포하는 경우가 아니라면 실질적으로 중요하기보다는 학습에 가깝습니다. 이러한 분산 캐시 저장소는 I/O에 묶여 있으며 일반적으로 네트워크 지연 시간이 데이터베이스 지연 시간보다 애플리케이션이 인지하는 지연 시간에 더 큰 영향을 미칠 수 있기 때문입니다.
보다 실용적인 성능 측면은 스토리지 효율성, 즉 동일한 양의 메모리에 얼마나 많은 데이터를 담을 수 있는지입니다. 여기에서도 Redis가 사용하는 내부 데이터 구조는 데이터 크기에 따라 달라집니다. 따라서 이러한 데이터베이스 간의 성능에 대한 모든 논의는 신중하게 접근해야 합니다.
2016년 연구 논문에 나타난 몇 가지 비교를 살펴보겠습니다. 이 논문에서 저자들은 널리 사용되는 인메모리 데이터베이스를 실험하여 다음과 같은 측면에서 성능을 측정하였습니다.
- 작업을 완료하는 데 걸리는 시간.
- 작업 중 메모리를 얼마나 효율적으로 사용하는지.
연구논문에 사용된 Redis와 Memcached 버전은 다음과 같습니다.
Database | Version |
Redis | 3.0.7 |
Memcached | 1.4.14 |
논문 원본을 보고 싶으신 분은 아래에 첨부해 두었으니 참고하세요.
Write Operation
아래 표에서 볼 수 있듯이 데이터를 기록하는 동안 Memcached는 레코드 수가 최대 100만 개까지 증가한 후에도 뛰어난 속도를 보여줍니다.
키-값 쌍을 쓰는 데 걸리는 소요 시간(ms)
Number of records | ||||
Database | 1,000 | 10,000 | 100,000 | 1,000,000 |
Redis | 34 | 214 | 1,666 | 14,638 |
Memcached | 23 | 100 | 276 | 2,813 |
Read Operation
Redis에서는 레코드가 백만 개가 있어도 데이터 읽기가 거의 일정하게 유지되지만, Memcached에서는 레코드 수가 증가함에 따라 시간도 조금씩 증가합니다.
주어진 키에 해당하는 값을 읽는 데 걸린 경과 시간(elapsed time: ms)
Number of records | ||||
Database | 1,000 | 10,000 | 100,000 | 1,000,000 |
Redis | 8 | 6 | 8 | 8 |
Memcached | 9 | 14 | 14 | 30 |
Memory Use
메모리 사용량은 아래 결과에서 볼 수 있듯이 Redis가 가장 적게 사용합니다.
쓰기 작업을 위한 인메모리 데이터베이스의 메모리 사용량(MB)
Number of records | ||||
Database | 1,000 | 10,000 | 100,000 | 1,000,000 |
Redis | 2.5 | 3.8 | 4.3 | 62.7 |
Memcached | 5.3 | 27.2 | 211 | 264.9 |
삭제 작업을 위한 인메모리 데이터베이스의 메모리 사용량(MB)
Number of records | ||||
Database | 1,000 | 10,000 | 100,000 | 1,000,000 |
Redis | 0 | 0 | 0 | 0 |
Memcached | 2.2 | 2.1 | 2.2 | 2.2 |
Redis와 Memcached 특징 비교 요약
지금까지 정리한 것을 토대로 멤캐시드와 레디스에 중요하게 비교되는 몇 가지 특징들이 있습니다. 중요한 요소들에 대해서는 아래 표를 참고하시면 될 것 같습니다.
Memcached | Redis | |
1밀리초 미만의 지연 시간 | 예 | 예 |
개발자 사용 편의성 | 예 | 예 |
데이터 파티셔닝 | 예 | 예 |
다양한 프로그래밍 언어 지원(redis가 좀 더 많음) | 예 | 예 |
고급 데이터 구조 | - | 예 |
다중 스레드 아키텍처 | 예 | - |
스냅샷 | - | 예 |
복제 | - | 예 |
트랜잭션 | - | 예 |
게시(Pub)/구독(Sub) | - | 예 |
Lua 스크립팅 | - | 예 |
지리 정보(GIS) 지원 | - | 예 |
결론
오늘은 레디스와 멤캐시드를 비교해 보았습니다. 전반적으로 레디스가 나아보이는데, 최근 레디스가 라이선스 정책을 바꿔서 이슈가 되고 있는것 같습니다.
사실 제가 아쉬운 점은 nosql 쪽의 분산 캐시 제품들은 모두 RDBMS 인터페이스와 달라서 사용하기가 좀 불편하다는 점이 있습니다.
그리고, 바꾸려고 해도 코드를 다시 짜야하는 문제도 있고요.
전체적으로 표준이 생기거나 SQL 인터페이스가 지원되면 좋을 것 같습니다.
'IT' 카테고리의 다른 글
잘 알려지지 않은 Redis로 할 수 있는지 5가지 - 사례 연구 (case study) (62) | 2024.04.30 |
---|---|
카우치베이스(couchbase) 서버 특징, 다운로드, 설치 및 구성하기 (3) | 2024.04.29 |
SQLite 튜닝하기 [1] - memory mapped I/O(mmap) 사용하기 (35) | 2024.04.18 |
우분투에서 파이썬으로 sqlite 사용하기 - python ubuntu linux (39) | 2024.04.17 |
파이썬 코루틴과 태스크 (Coroutines, Tasks) (43) | 2024.04.15 |