Redis 7.x ShardedPubSub 핵심 정리
Redis 7.x에서 새로 도입된 ShardedPubSub이 무엇이고 왜 필요한가요?
꼬리 질문
- 기존 PubSub의 한계점은 무엇이었나요?
- ShardedPubSub은 어떤 환경에서 특히 유용한가요?
답변 보기
✅ ShardedPubSub은 Redis Cluster 환경에서 메시지를 특정 샤드(슬롯) 그룹으로만 제한하여 브로드캐스팅하는 새로운 Pub/Sub 메커니즘입니다.
- 메시지가 모든 노드가 아닌 특정 샤드에만 전파되어 네트워크 오버헤드를 크게 감소시킵니다 📉
- CRC16 해싱을 사용하여 채널이 속할 슬롯을 결정하고, 해당 슬롯을 담당하는 노드들에게만 메시지를 전달합니다
- 꼬리질문: 기존 PubSub의 한계점은 무엇이었나요?
- 기존 PubSub은 메시지를 클러스터의 모든 노드에 브로드캐스팅했습니다 📡
- 노드 수가 증가할수록 네트워크 트래픽이 기하급수적으로 증가하는 문제가 있었습니다
- 불필요한 메시지 전파로 인한 성능 저하가 발생했습니다
- 꼬리질문: ShardedPubSub은 어떤 환경에서 특히 유용한가요?
- 대규모 Redis Cluster 환경에서 매우 효과적입니다 🏢
- 특정 데이터와 관련된 이벤트를 처리할 때 유용합니다
- 채널별로 메시지 격리가 필요한 멀티테넌트 환경에 적합합니다
ShardedPubSub과 기존 PubSub의 주요 차이점은 무엇인가요?
꼬리 질문
- 명령어 사용법은 어떻게 다른가요?
- 성능상 어떤 개선이 있나요?
답변 보기
✅ ShardedPubSub과 기존 PubSub의 핵심 차이점은 메시지 라우팅 방식입니다.
-
기존 PubSub: 메시지를 모든 노드로 전파
-
ShardedPubSub: 메시지를 특정 샤드에만 전파
-
명령어 차이:
- 기존:
subscribe
,publish
- Sharded:
ssubscribe
,spublish
- 기존:
-
성능 차이:
- 네트워크 부하: 기존 PubSub은 높음 ⬆️, ShardedPubSub은 낮음 ⬇️
- 확장성: 기존 PubSub은 제한적, ShardedPubSub은 우수
-
꼬리질문: 명령어 사용법은 어떻게 다른가요?
- 기존 PubSub:
SUBSCRIBE channel
,PUBLISH channel message
- ShardedPubSub:
SSUBSCRIBE channel
,SPUBLISH channel message
- 's' 접두사가 붙은 것 외에는 사용법이 동일합니다
- 채널 이름에 따라 자동으로 적절한 샤드로 라우팅됩니다
- 기존 PubSub:
-
꼬리질문: 성능상 어떤 개선이 있나요?
- 브로드캐스트 루프가 대폭 감소합니다 🔄
- 노드 간 통신 오버헤드가 줄어듭니다
- 특히 노드 수가 많을수록 성능 향상이 두드러집니다
- 메시지 전파 지연시간이 감소합니다
ShardedPubSub은 클러스터에서 어떻게 동작하나요?
꼬리 질문
- MOVED 리다이렉션은 어떻게 처리되나요?
- Primary와 Replica 노드에서의 동작은 어떻게 다른가요?
답변 보기
✅ ShardedPubSub은 CRC16 해싱을 통해 채널을 특정 슬롯에 매핑하고, 해당 슬롯을 담당하는 샤드 그룹 내에서만 메시지를 전파합니다.
- 동작 과정:
- 채널 이름을 CRC16으로 해싱하여 슬롯 번호 결정 (0-16383) 🎯
- 해당 슬롯을 담당하는 Primary 노드 식별
- Primary와 그 Replica들로 구성된 샤드 그룹 내에서만 메시지 전파
- 다른 샤드의 노드들은 메시지를 받지 않음
- 꼬리질문: MOVED 리다이렉션은 어떻게 처리되나요?
- 클라이언트가 잘못된 노드에 연결하면
-MOVED
응답을 받습니다 - 예:
-MOVED 12539 127.0.0.1:6382
- 클라이언트는 이 정보로 올바른 노드로 재연결해야 합니다
- Smart Client는 이를 자동으로 처리합니다
- 클라이언트가 잘못된 노드에 연결하면
- 꼬리질문: Primary와 Replica 노드에서의 동작은 어떻게 다른가요?
- Primary: 직접 메시지를 받고 Replica들에게 전파합니다
- Replica: Primary로부터 메시지를 받아 구독자에게 전달합니다
- 동일 샤드 내의 모든 노드가 메시지를 처리할 수 있습니다
- Failover 시에도 메시지 전달이 유지됩니다
ShardedPubSub을 사용할 때 주의사항과 한계점은 무엇인가요?
꼬리 질문
- 언제 ShardedPubSub을 사용하고, 언제 기존 PubSub을 사용해야 하나요?
- 패턴 구독(Pattern Subscribe)은 지원되나요?
답변 보기
✅ ShardedPubSub은 강력한 기능이지만 모든 상황에 적합한 것은 아니며, 몇 가지 제약사항이 있습니다.
- 주요 한계점:
- 채널이 특정 샤드에 고정되어 유연성이 제한됩니다 🔒
- 패턴 구독을 지원하지 않습니다 ❌
- 클라이언트가 클러스터 토폴로지를 알아야 합니다
- 여전히 대규모 Pub/Sub 시스템에는 구조적 한계가 있습니다
- 주의사항:
- 샤드 간 메시지 격리로 인해 글로벌 브로드캐스트가 불가능합니다
- 채널명 설계 시 해시 분산을 고려해야 합니다
- Hot Shard 문제가 발생할 수 있습니다 🔥
- 꼬리질문: 언제 ShardedPubSub을 사용하고, 언제 기존 PubSub을 사용해야 하나요?
- ShardedPubSub 사용:
- 대규모 클러스터 환경 ✅
- 채널별 격리가 필요한 경우 ✅
- 네트워크 오버헤드를 줄여야 할 때 ✅
- 기존 PubSub 사용:
- 모든 노드에 브로드캐스트가 필요한 경우 ✅
- 패턴 구독이 필요한 경우 ✅
- 작은 규모의 클러스터 ✅
- ShardedPubSub 사용:
- 꼬리질문: 패턴 구독(Pattern Subscribe)은 지원되나요?
- ShardedPubSub은 패턴 구독을 지원하지 않습니다 ❌
SPSUBSCRIBE
같은 명령어는 존재하지 않습니다- 패턴 구독이 필요하다면 기존 PubSub을 사용해야 합니다
- 이는 샤드 기반 라우팅과 패턴 매칭의 기술적 충돌 때문입니다
ShardedPubSub 사용 예시와 실제 구현 시 고려사항은 무엇인가요?
꼬리 질문
- 실제 코드에서는 어떻게 사용하나요?
- 마이그레이션 전략은 어떻게 세워야 하나요?
답변 보기
✅ ShardedPubSub은 기존 PubSub과 유사한 인터페이스를 제공하지만, 클러스터 환경에 최적화된 사용 패턴이 필요합니다.
- 기본 사용 예시:
# 구독
SSUBSCRIBE user:1234:events
# 발행
SPUBLISH user:1234:events "login successful"
- 구현 시 고려사항:
- 채널명에 데이터 키를 포함시켜 동일 샤드 보장 🎯
- Connection Pool을 샤드별로 관리
- Retry 로직과 Failover 처리 구현
- 모니터링과 메트릭 수집 체계 구축 📊
- 꼬리질문: 실제 코드에서는 어떻게 사용하나요?
- Python 예시 (redis-py):
# ShardedPubSub 사용 pubsub = redis_client.sharded_pubsub() pubsub.ssubscribe("channel:123") # 메시지 발행 redis_client.spublish("channel:123", "message")
- 클라이언트 라이브러리가 ShardedPubSub을 지원하는지 확인 필요
- 자동 재연결과 에러 처리 구현 필수
- 꼬리질문: 마이그레이션 전략은 어떻게 세워야 하나요?
- 단계적 마이그레이션:
- 신규 기능부터 ShardedPubSub 적용
- 트래픽이 적은 채널부터 순차 전환
- 듀얼 모드로 일정 기간 운영 후 완전 전환
- 체크리스트:
- 클라이언트 라이브러리 업그레이드 ✅
- 채널명 규칙 재설계 ✅
- 모니터링 대시보드 준비 ✅
- 롤백 계획 수립 ✅
분산락을 사용하는 경우, 락이 풀렸을 때 어떤 방식으로 동작하게 되나요? (락을 획득하게 되나요?)
답변 보기
-
✅ wait queue에서 대기하다가 이벤트를 받으면 락 획득을 시도한다는 이해는 맞습니다 (Redisson 기준)
-
❌ thread pool이 반환되면 queue에서 순차적으로 처리한다는 설명은 틀렸습니다
-
분산락 대기 방식은 구현체에 따라 다릅니다 📚
Lettuce (스핀락 방식) 🔄
- 99개의 대기 요청들이 실제 큐에서 기다리지 않음
- 각 요청이 개별적으로 Redis에 반복 요청 (폴링)
- 1초 동안 50ms마다 시도하면 100개 요청이 약 10,000번 Redis 호출
- 매우 비효율적이며 Redis에 큰 부하 발생
Redisson (Pub/Sub 방식) 📡
-
락 획득 실패한 클라이언트들이 Redis 채널을 구독
-
실제 "대기 큐" 개념에 가까운 구조
-
락 해제 시 구독자들에게 알림 전송
-
Redis 부하를 크게 줄임
-
꼬리질문: 이벤트가 발생하면 어떻게 처리되는걸까요?
- Redisson의 실제 처리 과정은 다음과 같습니다:
- 락 획득 실패 → threadId를 채널로 구독
- 락 보유자가 락 해제 → 해당 채널에 메시지 발행
- 모든 구독자가 동시에 알림 수신 ⚡
- 모든 대기 클라이언트가 동시에 락 획득 재시도
- 결국 경쟁을 통해 하나만 락 획득 성공
- Redisson의 실제 처리 과정은 다음과 같습니다:
-
꼬리질문: thread pool이 반환되면 queue에서 다음 작업을 꺼내서 처리하는 방식으로 동작하는게 맞나요?
- ❌ 이 설명은 틀렸습니다
- 분산락은 순차적 처리가 아닌 경쟁적 처리 방식입니다
- 일반 작업 큐: FIFO 순서로 하나씩 순차 처리 🏃♂️→🏃♀️→🚶♂️
- 분산락: 모든 대기자가 동시에 경쟁하여 처리 🏃♂️🏃♀️🚶♂️ (경쟁!)
- Thread pool은 단일 프로세스 내 스레드 관리 개념
- 분산락은 여러 서버/프로세스 간 동기화 메커니즘
- 두 개념은 서로 다른 계층에서 동작하는 별개의 기술입니다
핵심 포인트 💡
- 분산락의 대기자들은 "순서 보장된 큐"가 아닌 "구독자 집합"
- 락 해제 시 모든 대기자가 동시에 알림받고 경쟁
- FIFO 순서를 보장하지 않는 경쟁 기반 시스템
Redis 클러스터의 동작 방식에 대해 설명해주세요
꼬리 질문
- Redis 클러스터가 Hash 링 대신 Hash Slot을 사용하는 이유는 무엇인가요?
- MOVED 리다이렉션과 ASK 리다이렉션의 차이점은 무엇인가요?
- 16,384개의 슬롯 개수를 선택한 이유는 무엇인가요?
- CRC16 모듈로 연산이 무엇이고 어떤 특징을 갖고 있나요?
답변 보기
제시하신 설명 검토 결과 🔍
- ✅ Gossip 알고리즘으로 노드 상태 확인
- ❌ Hash 링 기반 동작 (실제로는 Hash Slot 방식)
- ✅ GET 요청 리다이렉트
- ❌ PUT 요청 내부 이동 (실제로는 리다이렉트 방식)
정확한 Redis 클러스터 동작 방식 🎯
- 16,384개의 Hash Slot 기반으로 데이터 분산
- CRC16 알고리즘으로 키를 해시하여 슬롯 결정
- Hash 링(Consistent Hashing)이 아닌 고정 슬롯 방식
- Gossip 프로토콜로 노드 간 상태 모니터링
- ping/pong 메시지를 통한 헬스체크
- PFAIL → FAIL 상태로 장애 감지
- MOVED 리다이렉션으로 요청 처리
- GET/PUT 모두 동일한 리다이렉트 방식
- 내부 자동 전달이 아닌 클라이언트 재요청 방식
꼬리질문: Redis 클러스터가 Hash 링 대신 Hash Slot을 사용하는 이유는 무엇인가요?
- 구현 단순성: CRC16 모듈로 연산이 Consistent Hashing보다 간단
- 균등 분산: 테스트 결과 키가 슬롯에 고르게 분산됨
- 노드 추가/제거 용이성: 슬롯 단위로 마이그레이션 가능
- 설정 전파 효율성: 16K 슬롯은 2KB 비트맵으로 전송 가능 (65K는 8KB 필요)
꼬리질문: MOVED 리다이렉션과 ASK 리다이렉션의 차이점은 무엇인가요?
- MOVED: 영구적인 슬롯 이동 완료 시 사용
- 클라이언트가 슬롯 테이블 업데이트 필요
- ASK: 일시적인 슬롯 마이그레이션 중 사용
- 리샤딩(resharding) 과정에서 발생
- 클라이언트가 일회성으로만 다른 노드에 요청
꼬리질문: 16,384개의 슬롯 개수를 선택한 이유는 무엇인가요?
- 메모리 효율성: 2KB 비트맵으로 슬롯 정보 저장 가능
- 네트워크 효율성: Gossip 메시지에 슬롯 정보 포함 시 2KB만 필요
- 클러스터 규모: 최대 1000개 마스터 노드 지원 목표에 적합
- 성능 최적화: CRC16의 14비트 활용으로 균등 분산 보장
꼬리질문: CRC16 모듈로 연산이 무엇이고 어떤 특징을 갖고 있나요? 🔢
- CRC16 정의: 16비트 순환 중복 검사(Cyclic Redundancy Check) 알고리즘
- 다항식 나눗셈을 기반으로 한 해시 함수
- 원래는 데이터 오류 검출을 위해 개발됨
- Redis에서의 활용:
CRC16(key) mod 16384
로 슬롯 계산 - 16비트 출력값을 16,384로 나눈 나머지 사용
- 14비트만 실제 활용 (2^14 = 16,384)
- 모듈로 2 연산 특징:
- 일반 뺄셈 대신 XOR 연산 사용
- 캐리(carry) 비트 무시하여 계산 단순화
- 하드웨어 구현에 최적화됨
- 분산 성능:
- 균등 분포 보장: 다양한 키 패턴에서 고른 분산
- 빠른 계산: 단순한 비트 연산으로 고속 처리
- 결정적 결과: 같은 키는 항상 같은 슬롯에 할당
Redis Cluster의 Gossip Protocol은 어떻게 동작하나요?
꼬리 질문
- PFAIL과 FAIL 상태의 차이점과 전환 조건은 무엇인가요?
- Gossip 메시지에는 어떤 정보들이 포함되나요?
- Split Brain 상황을 어떻게 방지하나요?
답변 보기
✅ Gossip Protocol은 Redis Cluster의 노드 간 상태 정보를 교환하는 P2P 통신 프로토콜입니다.
Gossip Protocol의 핵심 동작 원리 🔄
- 각 노드는 주기적으로 다른 노드들과 정보를 교환
- 전체 브로드캐스트가 아닌 일부 노드와만 통신 (효율성)
- 정보가 점진적으로 전파되어 최종적 일관성 달성
- 중앙 조정자 없이 분산된 방식으로 동작
메시지 타입과 역할 📨
- PING: 다른 노드에게 자신의 상태 정보 전송
- 1초마다 랜덤으로 선택된 노드에게 전송
- 자신의 상태 + 알고 있는 다른 노드들의 정보 포함
- PONG: PING에 대한 응답
- 수신 노드의 현재 상태 정보 포함
- 정보 동기화의 핵심 메커니즘
- MEET: 새 노드를 클러스터에 추가
CLUSTER MEET
명령으로 트리거- 핸드셰이크 프로세스 시작
- FAIL: 노드 장애 확정 메시지
- 과반수가 동의한 장애를 전체에 알림
- 즉시 전파 (긴급 메시지)
장애 감지 프로세스 🚨
- 타임아웃 감지 (NODE_TIMEOUT/2)
- 기본값: 15초의 절반인 7.5초
- 응답이 없으면 PFAIL 상태로 마킹
- PFAIL (Possible Fail) 상태
- 단일 노드의 주관적 판단
- "이 노드가 문제있는 것 같다"
- 아직 확정되지 않은 상태
- FAIL 확정 조건
- 과반수 이상의 마스터가 PFAIL로 판단
- NODE_TIMEOUT 시간 내에 과반수 동의
- FAIL 메시지가 전체 클러스터에 즉시 전파
꼬리질문: PFAIL과 FAIL 상태의 차이점과 전환 조건은 무엇인가요?
- PFAIL (Possible Fail) 🤔
- 개별 노드의 주관적 판단
- "A가 B를 PFAIL로 본다"는 의미
- 실제 네트워크 파티션일 수도 있음
- 복구 가능한 일시적 상태
- FAIL (Confirmed Fail) ❌
- 클러스터 전체의 객관적 합의
- 과반수 마스터가 동일 노드를 PFAIL로 판단
- Failover 프로세스 자동 시작
- 해당 노드는 클러스터에서 제외됨
- 전환 조건 (과반수 감지 메커니즘):
- 각 노드는 Gossip 메시지로 PFAIL 정보 수집
- Gossip에 "송신자가 보는 다른 노드들의 상태" 포함
- PFAIL 보고 수 > 전체 마스터 수 / 2 시 FAIL 확정
- NODE_TIMEOUT 시간 내 과반수 달성 필요
- 예: 5개 마스터 중 3개 이상이 PFAIL 판단
- FAIL 확정 시 즉시 전체 클러스터에 브로드캐스트
꼬리질문: Gossip 메시지에는 어떤 정보들이 포함되나요?
- 노드 식별 정보 🆔
- Node ID (40자리 16진수)
- IP 주소와 포트 번호
- 클러스터 버스 포트 (기본: 데이터 포트 + 10000)
- 상태 정보 📊
- 노드 플래그 (master/slave/pfail/fail)
- 현재 epoch (클러스터 설정 버전)
- 담당 슬롯 비트맵 (2KB)
- 복제 정보 🔗
- Master Node ID (Replica인 경우)
- 복제 오프셋 정보
- 타이밍 정보 ⏰
- 마지막 PING/PONG 시간
- 노드별 타임스탬프
꼬리질문: Split Brain 상황을 어떻게 방지하나요?
- 과반수 원칙 (Quorum) ⚖️
- 과반수 마스터가 동의해야 FAIL 확정
- 과반수가 없으면 쓰기 거부 (cluster-require-full-coverage)
- 소수 파티션은 자동으로 읽기 전용 모드
- 홀수 개 마스터 노드 유지 권장 (Redis 공식 문서)
- Epoch 메커니즘 🔢
- 각 설정 변경마다 configEpoch 증가
- "Last failover wins" 원칙: 높은 epoch가 우선권
- Failover 시 새 마스터는 더 높은 configEpoch 부여
- 한계: Split Brain을 크게 줄이지만 완전 방지는 불가
- 출처: Redis Cluster Specification (redis.io)
- 투표 메커니즘 🗳️
- Replica 승격에 과반수 마스터 투표 필요
- NODE_TIMEOUT * 2 동안 재투표 불가
- 이전 epoch의 투표는 무시
- 자동 Failover 제한 🛡️
- Replica는 과반수 마스터와 연결된 경우만 승격
- 네트워크 파티션된 Replica는 승격 불가
- 동시 다발적 failover 방지
- 실제 시나리오 💡
- 5노드 클러스터가 3:2로 분할
- 3노드 그룹: 과반수 확보로 정상 운영
- 2노드 그룹: 과반수 미달로 쓰기 중단
- 재연결 시 높은 configEpoch 기준으로 일관성 복구
- Best Practices 📋
- 최소 3개 복제본 유지 (마스터 1 + Replica 2)
- 적절한 NODE_TIMEOUT 설정
- Redis Enterprise 사용 시 추가 안전장치 활용
- 출처: Redis Learn (opens in a new tab), Medium 기술 블로그 (opens in a new tab)
Redis Cluster 구조에서 Replica가 있다면 Master 노드에는 쓰기연산만하고 Replica 노드에는 읽기 연산만 하는 방식으로 동작하나요?
꼬리 질문
- Replica에서 읽기를 활성화하려면 어떻게 해야 하나요?
- 일반적인 Master-Slave 구조와 Redis Cluster는 어떤 차이가 있나요?
- Redis Cluster의 데이터 일관성은 어떻게 보장되나요?
답변 보기
❌ 아니요, Redis Cluster는 기본적으로 Master 노드가 읽기와 쓰기를 모두 처리합니다.
-
Redis Cluster의 기본 동작 방식
- Master 노드 📝: 읽기와 쓰기 연산을 모두 처리
- Replica 노드 💾: 주로 고가용성을 위한 백업 역할 (failover 대비용)
- Replica는 자동으로 읽기 작업을 분산하지 않음
-
꼬리질문: Replica에서 읽기를 활성화하려면 어떻게 해야 하나요?
- READONLY 명령을 사용하면 Replica 노드에서도 읽기 가능
READONLY
- Replica에서 읽기 허용 (stale 데이터 허용)READWRITE
- 다시 일반 모드로 전환- 클라이언트가 명시적으로 설정해야 함 ⚠️
- 약간 오래된 데이터를 읽을 수 있음을 감수해야 함
-
꼬리질문: 일반적인 Master-Slave 구조와 Redis Cluster는 어떤 차이가 있나요?
- 일반 Master-Slave: 자동으로 읽기 분산이 가능
- Redis Cluster:
- 주 목적은 데이터 샤딩 (데이터를 여러 노드에 분산 저장)
- Replica는 읽기 분산이 아닌 고가용성이 주목적
- 읽기 분산을 원하면 클라이언트가 직접 설정 필요
-
꼬리질문: Redis Cluster의 데이터 일관성은 어떻게 보장되나요?
- 비동기 복제 방식 사용 🔄
- Master가 쓰기를 승인 → 이후 Replica로 전파
- 네트워크 파티션이나 Master 장애 시 쓰기 손실 가능성 존재 ⚡
- READONLY 사용 시 최신이 아닌 데이터를 읽을 수 있음
- 강한 일관성(Strong Consistency)을 보장하지 않음
Redis Stream에서 XREAD와 XREADGROUP의 동작 차이는 무엇인가요?
꼬리 질문
- 1번 컨슈머가 XREAD key1, 2번 컨슈머가 XREAD key1을 실행하고 XADD key1 "hello world"가 발생하면 어떻게 될까요?
- Consumer Group을 사용하면 채팅방 서비스 구현이 어려운 이유는 무엇인가요?
답변 보기
-
✅ XREAD: Fan-out(브로드캐스트) 방식으로 동작 📡
- 같은 Stream에 여러 클라이언트가 접근하면 모든 Consumer가 동일한 메시지를 받음
- 채팅방처럼 모든 참여자에게 메시지를 전달해야 하는 경우에 적합
-
✅ XREADGROUP: 분산 처리 방식으로 동작 ⚡
- Consumer Group 내에서 각 Consumer가 서로 다른 메시지를 나눠서 처리
- 작업 부하 분산이나 병렬 처리가 필요한 경우에 적합
-
꼬리질문: 1번 컨슈머가 XREAD key1, 2번 컨슈머가 XREAD key1을 실행하고 XADD key1 "hello world"가 발생하면 어떻게 될까요?
- ✅ 두 컨슈머 모두 "hello world" 메시지를 받습니다
- XREAD는 N-client에 대한 fan-out을 제공하기 때문
-
꼬리질문: Consumer Group을 사용하면 채팅방 서비스 구현이 어려운 이유는 무엇인가요?
- ❌ Consumer Group은 분산 처리 방식이므로 한 메시지가 한 Consumer에게만 전달됨
- 채팅방은 브로드캐스트가 필요한데, Consumer Group은 이와 반대로 동작
- 해결책: Redis Pub/Sub 사용 권장 💬
참조한 내용 (XREAD와 XREADGROUP 차이) (opens in a new tab)
참조한 내용 (XREAD 공식문서) (opens in a new tab)
참조한 내용 (XREADGROUP 공식문서) (opens in a new tab)
Redis Stream의 PEL과 ACK는 무엇이며 어떤 역할을 하나요?
꼬리 질문
- ACK를 보내면 다음 Consumer가 읽을 stream 위치가 변경되나요?
- PEL은 언제 생성되고 언제 제거되나요?
- XREAD로 받은 메시지도 ACK가 필요한가요?
답변 보기
-
✅ PEL(Pending Entries List): Consumer Group에서 전달되었지만 아직 ACK되지 않은 메시지 목록 📋
- 각 Consumer별로 개별 관리되는 미처리 메시지 리스트
- 장애 복구와 메시지 재처리를 위한 핵심 메커니즘
-
✅ ACK의 역할: 메시지 처리 완료를 Redis에 알리는 명령어 ✅
- XREADGROUP으로 받은 메시지에만 사용
- PEL에서 해당 메시지를 제거하는 용도
-
꼬리질문: ACK를 보내면 다음 Consumer가 읽을 stream 위치가 변경되나요?
- ❌ ACK는 읽기 위치에 영향을 주지 않습니다
- Consumer Group의
last_delivered_id
는 ACK와 무관하게 증가 - ACK는 오직 PEL 관리를 위한 목적으로만 사용
-
꼬리질문: PEL은 언제 생성되고 언제 제거되나요?
- 생성 시점: XREADGROUP으로 메시지를 읽었을 때 자동 생성 📥
- 제거 시점: XACK 명령어로 명시적으로 제거 🗑️
- 제거하지 않으면 메모리 누수와 장애 복구 문제 발생 가능
-
꼬리질문: XREAD로 받은 메시지도 ACK가 필요한가요?
- ❌ XREAD는 ACK 불필요
- XREAD는 PEL을 생성하지 않기 때문
- 오직 XREADGROUP으로 받은 메시지만 ACK 필요
참조한 내용 (PEL과 ACK) (opens in a new tab)
참조한 내용 (Redis Stream 기본) (opens in a new tab)
참조한 내용 (XACK 명령어) (opens in a new tab)
XPENDING과 XCLAIM은 어떻게 활용하며 어떤 차이가 있나요?
꼬리 질문
- Consumer가 메시지를 받고 처리하다가 실패했을 때의 복구 과정은?
- XCLAIM은 "재전송"인가요 "소유권 이전"인가요?
- XAUTOCLAIM과 XCLAIM의 차이점은?
답변 보기
-
✅ XPENDING: Pending된 메시지들을 조회하는 명령어 🔍
- Consumer Group 내 미처리 메시지 현황 파악
- 어떤 Consumer가 어떤 메시지를 얼마나 오래 처리 중인지 확인
-
✅ XCLAIM: 메시지의 소유권을 다른 Consumer로 이전하는 명령어 🔄
- 실패한 Consumer의 메시지를 정상 Consumer가 대신 처리
- 장애 상황에서 메시지 처리 연속성 보장
-
꼬리질문: Consumer가 메시지를 받고 처리하다가 실패했을 때의 복구 과정은?
- XPENDING으로 미처리 메시지 발견 🕵️♂️
- XCLAIM으로 정상 Consumer에게 소유권 이전 📮
- 새로운 Consumer가 메시지 처리 후 XACK ✅
- PEL에서 완전히 제거되어 복구 완료 🎉
-
꼬리질문: XCLAIM은 "재전송"인가요 "소유권 이전"인가요?
- ✅ **"소유권 이전"**이 정확한 표현
- 메시지 자체는 변하지 않고, 담당 Consumer만 변경됨
- 원래 Consumer의 PEL에서 제거 → 새 Consumer의 PEL로 이동
-
꼬리질문: XAUTOCLAIM과 XCLAIM의 차이점은?
- XCLAIM: 수동으로 특정 메시지 ID를 지정해서 소유권 이전
- XAUTOCLAIM: 일정 시간 이상 Pending된 메시지를 자동으로 claim (Redis 6.2+)
- XAUTOCLAIM이 더 편리하고 자동화된 방식
참조한 내용 (XPENDING) (opens in a new tab)
참조한 내용 (XCLAIM) (opens in a new tab)
참조한 내용 (XAUTOCLAIM) (opens in a new tab)
Redis Stream의 내부 자료구조는 어떻게 구성되어 있나요?
꼬리 질문
- Entry ID는 어떤 구조로 되어 있나요?
- Radix Tree와 Listpack을 사용하는 이유는 무엇인가요?
- Redis Stream의 메모리 최적화 전략은?
답변 보기
-
✅ Radix Tree of Listpacks: Redis Stream의 핵심 자료구조 🌳
- Radix Tree: Entry ID 기반의 효율적인 인덱싱과 범위 검색
- Listpack: 연속된 메모리 블록에 여러 entry를 압축 저장 (Redis 7.0+)
-
✅ 메모리 최적화: 지연 삭제(Lazy Deletion) 전략 사용 🗑️
- XDEL로 삭제 시 즉시 메모리 해제하지 않고 "삭제 마크" 표시
- Macro-node 내 모든 entry가 삭제되었을 때만 메모리 회수
-
꼬리질문: Entry ID는 어떤 구조로 되어 있나요?
- ✅ 2개 부분으로 구성:
밀리초타임스탬프-시퀀스번호
⏰- ms: 64비트 밀리초 타임스탬프 (현재 시각)
- seq: 64비트 시퀀스 번호 (동일 밀리초 내 구분용)
- 예시:
1640995200000-0
- ✅ 2개 부분으로 구성:
-
꼬리질문: Radix Tree와 Listpack을 사용하는 이유는 무엇인가요?
- Radix Tree: ID 기반 빠른 검색과 범위 쿼리 지원 🚀
- Listpack: 메모리 압축으로 공간 효율성 극대화 💾
- 조합 효과: 빠른 성능 + 낮은 메모리 사용량 달성
-
꼬리질문: Redis Stream의 메모리 최적화 전략은?
- 지연 삭제: 즉시 메모리 해제 대신 삭제 마크 표시
- Listpack 압축: 연속 메모리 사용으로 단편화 방지
- 단편화 방지: 50% 이상 삭제되면 재구성 권장
참조한 내용 (Redis Stream 인코딩) (opens in a new tab)
참조한 내용 (메모리 최적화) (opens in a new tab)
참조한 내용 (모듈 API) (opens in a new tab)