Using Redis Streams instead of Kafka - Redis Special Topics (2/4) | System Design
- Redis는 키-값 데이터 스토어임에도 불구하고 Redis Stream이라는 특수 데이터 구조를 사용하여 Kafka와 유사한 스트림 처리 기능을 제공합니다. 💡
- 스트림 처리의 간단한 예시는 여러 분산 서비스에서 생성된 로그를 수집하여 보안 처리, 아카이빙 등 여러 대상으로 분배하는 것입니다. 🪵
- Redis List는 큐를 구현할 수 있으며, 데이터가 들어올 때까지 기다리는 블로킹 팝(blocking pop)을 지원하지만, 동일 데이터를 여러 소비자에게 보내는 팬아웃(fan-out)은 어렵습니다. 📜
- Redis Stream은 Kafka와 유사하게 메시지 ID와 미니 딕셔너리 형태의 값을 가지는 '추가 전용 로그(append-only log)' 구조입니다. ➕
- Kafka는 데이터를 디스크에 저장하고 OS 페이지 캐시를 활용하여 내구성과 성능을 확보하는 반면, Redis는 기본적으로 인메모리 저장소로 매우 빠르며 스냅샷 등의 메커니즘으로 내구성을 지원합니다. 💾
- Redis Stream은 오프셋(offset)을 지정하여 블로킹 읽기(blocking read)를 통해 새로운 데이터를 소비할 수 있으며, 여러 소비자가 동일한 데이터를 모두 받을 수 있는 팬아웃 시나리오를 지원합니다. ➡️
- Redis Stream의 파티셔닝은 여러 키(key)를 사용하여 구현됩니다. 생산자는 메시지를 해싱하여 특정 키에 데이터를 추가하고, 소비자는 특정 스트림을 소비하거나 모든 파티션에서 데이터를 읽을 수 있습니다. 🧩
- Redis Stream은 내부적으로 Radix Tree를 사용하여 구현되며, ID는 타임스탬프와 순차 번호로 구성되어 시간 기반의 범위 쿼리(range query)를 효율적으로 수행할 수 있습니다. 🌳
- 소비자 그룹(Consumer Group)은 여러 실제 소비자로 구성된 가상 소비자로, 그룹 내에서 각 데이터가 단 하나의 소비자에게만 전달되도록 보장하며, 여러 소비자 그룹으로 데이터를 팬아웃할 수 있습니다. 👥
- Kafka의 소비자 그룹은 처리량 분산을 위해 파티션에 걸쳐 소비자를 분배하는 데 중점을 두는 반면, Redis Stream의 소비자 그룹은 단일 스트림에 연결된 여러 소비자 간의 로드 밸런싱에 중점을 둡니다. ⚖️
- Redis Stream의 소비자 그룹은 그룹별 오프셋을 Redis에 저장하고,
READGROUP 명령을 통해 오프셋을 원자적으로 업데이트하며 데이터를 읽어, 여러 소비자가 동일한 레코드를 읽지 않도록 보장합니다. 🎯
- Redis Stream은 각 소비자에게 전송되었지만 아직 처리되지 않은 메시지 목록을 포함하는 '보류 목록(pending list)'을 통해 내결함성을 제공하여, 소비자가 실패하더라도 재접속 시 미처리 메시지를 다시 받을 수 있습니다. ✅
- Redis Stream 소비자 그룹은 소비자가 자체 속도로 로드 밸런싱을 수행하며, 소비자 그룹에서 데이터를 읽는 것은 오프셋 업데이트로 인해 '쓰기(write)' 작업으로 간주됩니다. ✍️
데브허브 | DEVHUB | Using Redis Streams instead of Kafka - Redis Special Topics (2/4) | System Design