1. Redis Streams 소개
- Redis Streams는 Redis 5.0에서 도입된 새로운 데이터 타입으로, 추가 전용(append-only) 로그 구조를 기반으로 하는 강력한 스트리밍 데이터 처리 기능을 제공합니다.
- 기존의 단순한 로그 구조를 넘어서 다음과 같은 고급 기능들을 제공합니다:
- O(1) 시간 복잡도의 랜덤 액세스
- 소비자 그룹을 통한 복잡한 소비 전략 구현
- 실시간 이벤트 기록 및 동시 배포
- 메시지 영속성과 장애 복구
1.1 주요 활용 사례
- 이벤트 소싱 (사용자 행동, 클릭 등의 추적)
- 센서 모니터링 (필드 디바이스의 데이터 수집)
- 알림 시스템 (사용자별 알림 이력 관리)
- 실시간 데이터 분석 파이프라인
- 분산 시스템 간 메시지 전달
2. 기본 개념과 명령어
2.1 스트림 항목과 ID
Redis Streams의 각 항목은 고유한 ID를 가지며, 이는 타임스탬프와 시퀀스 번호로 구성됩니다:
<millisecondsTime>-<sequenceNumber>
예시:
> XADD mystream * sensor-id 1234 temperature 19.8
"1692632086370-0"
2.2 핵심 명령어
- XADD: 스트림에 새 항목 추가
- XREAD: 스트림에서 항목 읽기
- XRANGE: 지정된 ID 범위의 항목 조회
- XLEN: 스트림의 항목 개수 반환
- XGROUP: 소비자 그룹 관리
- XREADGROUP: 소비자 그룹을 통한 항목 읽기
- XACK: 메시지 처리 완료 확인
3. 소비자 그룹을 통한 메시지 처리
- 소비자 그룹은 여러 클라이언트가 스트림의 메시지를 분산 처리할 수 있게 해주는 핵심 기능입니다.
- 하나의 스트림에 여러 소비자 그룹을 생성하는 것도 가능합니다.
3.1 소비자 그룹의 특징
- 메시지는 그룹 내 하나의 소비자에게만 전달
- 소비자별로 고유한 이름 식별
- 명시적인 메시지 처리 확인(ACK) 필요
- 미처리 메시지 추적 및 재처리 가능
3.2 소비자 그룹 사용 예시
# 소비자 그룹 생성
> XGROUP CREATE mystream mygroup $
# 소비자 A로 메시지 읽기
> XREADGROUP GROUP mygroup consumer-a COUNT 1 STREAMS mystream >
# 메시지 처리 완료 확인
> XACK mystream mygroup 1692632086370-0
4. 실제 도입 사례: LINE VOOM의 실시간 추천 시스템
- LINE의 SNS 서비스인 VOOM에서는 실시간 콘텐츠 추천을 위해 Redis Streams를 도입 사례를 같이 보고 실제 도입 시 주의사항을 알아봅니다.
- 참고: 실시간 추천 서비스를 위해 메시지 큐잉 도입하기(with Redis Streams)
4.1 도입 배경
- 기존의 하루 1회 배치 처리 방식으로는 실시간 이벤트나 새로운 뉴스 반영이 어려움
- Go 채널 기반 구현의 한계(메시지 영속성, 장애 복구 등의 문제)
- 확장 가능하고 안정적인 메시지 처리 시스템 필요
4.2 Redis Streams 선택 이유
- 사내 인프라 활용 가능
- 안정적인 메시지 재처리
- 소비자 그룹을 통한 부하 분산
- 간편한 모니터링과 운영
4.2 초기 구현 시 발생한 문제
- LINE의 경우 Redis Streams 도입 4일 만에 메모리 경고가 발생했습니다
- 예상: 한 달 이상의 메시지 보관 가능 (계산상 약 60일)
- 실제: 4일 만에 메모리 60% 이상 사용
- 해당 문제는 아래에서 설명할 메모리 관리 전략을 통해 해결되었습니다.
5. 주요 도입 시 주의사항
5.1 클러스터 환경에서의 메모리 관리
- Redis Streams를 클러스터에서 사용할 때는 다음 특성을 반드시 이해해야 합니다
- Redis에서 Streams는 키-값 구조를 따르는데, 여기서 스트림의 이름이 키가 되고 스트림의 데이터가 값으로 저장됩니다.
- 이때 주목해야 할 중요한 특징이 있습니다:
- 단일 샤드 저장
- Redis 클러스터는 CRC16을 사용해 키를 특정 해시 슬롯에 매핑합니다
- 하나의 스트림은 항상 하나의 해시 슬롯에만 매핑되므로, 모든 데이터가 단일 샤드에 집중됩니다
- 결과적으로 스트림의 데이터는 클러스터 전체에 분산되지 않고 특정 샤드에 집중되는 현상이 발생합니다
- 운영 시 고려사항
- 각 스트림의 크기를 모니터링하고 적절히 제한하기
- 데이터 보관 기간을 명확히 설정하여 메모리 사용량 관리하기
- 대용량 데이터 처리 시 여러 스트림으로 분산하는 전략 고려하기
5.2 해결 방안
- LINE이 적용한 데이터 분산 전략은 다음과 같습니다
- LINE의 사례에서 핵심은 "모든 샤드에 적어도 하나의 키가 배정되기 위해 필요한 평균적인 Stream 키의 개수는 얼마인가?"라는 문제를 해결하는 것입니다.
- 쿠폰 수집가 문제(Coupon Collector's Problem) 활용
- n개의 샤드에 균등하게 분배하기 위한 수학적 접근
- 6개 샤드 기준, 95% 신뢰도로 18개의 스트림 사용
- 실제로 18개의 키를 생성해 보니, 키들이 샤드에 균등하게 배분되는 것을 확인
- 실제 구현 시 고려사항
- 스트림의 수는 샤드 수와 원하는 신뢰도 수준에 따라 결정
- 각 스트림의 크기를 지속적으로 모니터링
- 데이터 보관 기간을 명확히 설정하여 관리