Message Broker(메시지 브로커)
메시지 브로커는 크게 메시징 큐와 이벤트 스트림 두 가지 형태로 나뉘는데, 레디스는 일반적으로 List 자료구조를 활용한 메시징 큐(Message Queue)로 활용된다. Stream 자료구조를 활용한 이벤트 스트림(Event Stream)도 지원하고 있으며, 카프카와 유사한 기능을 갖고 있다.
Messaging Queue vs Event Stream
메시지 소비 방식
소비 후 큐에서 제거
여러 소비자가 독립적으로 구독 가능
메시지 순서 보장
일반적으로 순서 보장
파티션 내 순서 보장, 전체 순서는 비보장
처리 방식
작업 단위(Task) 처리 중심
이벤트 기록(Event Log) 중심
재처리 지원
기본적으로 지원되지 않음
오프셋 기반으로 재처리 가능
데이터 흐름 방향
생산자가 소비자의 큐로 직접 전송 (Push)
생산자가 로그 저장소에 저장, 소비자가 직접 Pull
데이터 영속성
일반적으로 단기 저장 (일정 시간 후 삭제)
디스크 기반 장기 저장 가능
소비자 관계
일반적으로 일대일 관계
일대다(다대다) 구독 모델 지원
대표 예시
RabbitMQ, ActiveMQ
Kafka, AWS Kinesis
pub/sub 메시징 큐
레디스의 Pub/Sub 기능은 다음과 같은 특징을 갖는 메시징 큐(Message Queue)로 활용된다.
최소한의 메시지 전달 기능: 메시지를 단순히 발행하고 구독자에게 전달하는 기능 제공
전달 보장 없음: 수신 여부 확인이나 재전송 기능이 없어, 메시지는 수신자가 구독 중이 아닐 경우 유실
알림, 캐시 무효화 등 신뢰성보다 속도가 중요한 fire-and-forget 상황에 적합
브로드캐스트 방식: 구독 중인 모든 소비자에게 메시지를 브로드캐스트하여 전달
기본 명령어 예시
# 소비자 (구독)
SUBSCRIBE channel-name
# 생산자 (발행)
PUBLISH channel-name "message content"
이 방식은 별도 큐 저장 없이 채널을 통해 메시지를 브로드캐스팅하며, 메시지는 실시간으로 소비되지 않으면 유실된다.
클러스터 구조에서의 pub/sub
레디스 클러스터 구조에서도 Pub/Sub 기능을 사용할 수 있지만, 권장되는 사용 방식은 아닌데, 그 이유는 다음과 같다.
메시지 발행 절차: 클러스터의 한 노드에서 메시지를 발행하면, 해당 메시지는 클러스터 내 모든 노드로 전파
클러스터 목적과의 충돌: 클러스터는 데이터를 분산 저장하고 병렬 처리 효율을 높이기 위해 사용되는데, 모든 노드에 동일 메시지를 복제하는 구조는 목적에 맞지 않음
부작용: 메시지 전파로 인해 각 노드가 동일 데이터를 처리하게 되어 리소스 낭비, 네트워크 부하 등의 문제가 발생함
sharded pub/sub
Redis 7.0부터 도입된 Sharded Pub/Sub은 기존 Pub/Sub의 클러스터 비호환 문제를 해결하기 위해 고안된 방식이다. 각 채널은 슬롯에 매핑되어, 같은 슬롯을 가지고 있는 노드 간에만 메시지를 전달하는 구조를 갖는다.
메시지 해싱 및 라우팅: 채널명이 해시되어 특정 슬롯에 매핑되며, 해당 슬롯을 담당하는 노드에서 메시지를 처리
노드 간 전파 제거: 메시지가 모든 노드로 퍼지지 않고 특정 노드에서만 처리되어 불필요한 트래픽 및 부하 감소
List 메시징 큐
레디스의 List 자료구조는 LPUSH
, RPUSH
, LPOP
, RPOP
명령어로 양쪽 끝에서 삽입과 삭제가 가능한 자료구조로, 메시징 큐에 적합한 특성을 가지고 있다.
빠른 처리 속도와 순서 보장과 같은 장점도 존재하지만, 아래와 같은 기능을 통해 더욱 유용하게 활용할 수 있다.
EX 기능
데이터를 저장하고자 하는 list가 이미 존재할 때만 데이터를 삽입할 수 있는 기능
이미 캐시된(자주 사용되는) 리스트에만 데이터를 삽입할 수 있어, 불필요한 데이터 삽입 방지
블로킹 기능
이벤트 큐에 데이터가 있는지 확인하는 과정에서 불필요하게 리소스가 소도되는 것을 방지하는 기능
BLPOP
,BRPOP
명령어는 데이터가 있으면 즉시 반환하고, 데이터가 없으면 설정된 시간 동안 대기하는 기능을 제공
원형 큐
특정 아이템을 반복 접근해야하는 구조에서 사용할 수 있는 기능
RPOPLPUSH
명령어를 사용하여, 리스트의 마지막 아이템을 꺼내고 다시 첫 번째 아이템으로 삽입하는 방식으로 구현
참고자료
Last updated
Was this helpful?