본문으로 건너뛰기

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의 실시간 추천 시스템

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개의 키를 생성해 보니, 키들이 샤드에 균등하게 배분되는 것을 확인
  • 실제 구현 시 고려사항
    • 스트림의 수는 샤드 수와 원하는 신뢰도 수준에 따라 결정
    • 각 스트림의 크기를 지속적으로 모니터링
    • 데이터 보관 기간을 명확히 설정하여 관리

6. 운영 모범 사례

6.1 모니터링

  • 스트림 크기와 메모리 사용량 추적
  • 소비자 지연 모니터링
  • 미처리 메시지 수 확인

6.2 장애 대응

  • 페일오버 상황 대비 데이터 복제 설정
  • 소비자 그룹 상태 주기적 백업
  • 장애 복구 절차 문서화

7. 결론

  • Redis Streams는 실시간 데이터 처리를 위한 강력한 도구이지만, 효과적인 활용을 위해서는 적절한 설계와 운영 전략이 필요합니다.
  • 특히 클러스터 환경에서는 데이터 분산과 메모리 관리에 주의를 기울여야 합니다.
  • LINE의 사례에서 보듯이, 적절한 운영 전략과 모니터링을 통해 안정적인 실시간 데이터 처리 시스템을 구축할 수 있습니다.