메시지 플랫폼
RabbitMQ, Redis, Kafka의 특징
[Server/MSA] RabbitMQ, Redis, Kafka 란?
MQ 비교 (Kafka, RabbitMQ, Redis)
PUB/SUB, 잘 알고 쓰자!
RabbitMQ
, Redis
, Kafka
같은 기술을 메시지 플랫폼이라고 함
- 메시지 플랫폼은 2가지 종류가 존재
- 메시지 브로커는 이벤트 브로커의 역할을 할 수 없지만 이벤트 브로거는 메시지 브로커의 역할을 할 수 있음
- 서버에 많은 요청이 한 번에 들어오면 처리하지 못할 수 있음
- 처리하지 못한 데이터는 손실되어 서비스에 치명적인 영향을 줄 수 있음
- 따라서 유저의 요청이 들어오면 일단 요청을 큐에 넣어놓고 서버가 처리할 수 있을 때 데이터를 가져감
- 메시지는 삭제되지만 이벤트는 삭제하지 않음
- 메시지 브로커는 이벤트 브로커가 될 수 없으나 이벤트 브로커는 메시지 브로커가 될 수 있음
- 메시지는 삭제되고 이벤트는 삭제되지 않기 때문
- 메시지 큐 모델과 Pub/Sub 이벤트 스트림 모델을 구분할 수 있음
Tip! Pub/Sub 모델 의 구조
- 이벤트 (=메시지) 를 발행하는 Publisher 가 존재하며 Publisher 는 특정 Channel ( 혹은 Topic ) 에 이벤트를 전송
- 특정 Channel ( 혹은 Topic ) 을 구독하는 Subscriber 가 존재하며 Publisher 에 관계 없이 발행된 이벤트를 받을 수 있음
- 이때 구체적인 Pub ( 발행 ) / Sub ( 구독 ) 방식이 각 서비스마다 다른데 대표적으로
Redis
와 kafka
가 있음
메시지 브로커
- 대규모 메시지 기반 미들웨어 아키텍쳐에서 사용
- 미들웨어: 애플리케이션과 이들이 동작하는 인프라 간의 효율적인 연결을 위해 존재하는 소프트웨어
- 예시: 메시지 플랫폼, 인증 플랫폼, 데이터베이스
- 메시지를 받아서 적절히 처리하면 짧은 시간 내에 메시지가 삭제되는 특징이 있음
- 메시지를 받아서 처리하면 짧은 시간 안에 메시지가 삭제됨
- 손실되면 안되는 요청을 처리할 때에는 주의해야 함
Tip! 마이크로 서비스 통신: 동기 VS 비동기
- 동기식
- 요청을 보내면 응답이 올 때까지 기다리고 처리
- HTTP 위에서 REST 프로토콜을 사용
- 비동기식
- 응답과 상관없이 요청을 보냄
- 분산형 시스템에 적합하고 메시지 브로커 를 통해서 메세지를 관리
- 메세지 브로커: 송신자의 메세지 프로토콜 형식에서 수신자의 메세지 프로토콜 형식으로 변환하는 중간 모듈
- 무엇을 선택?
- 마이크로 서비스를 구성하는 방법과 인프라 ∙ 대기시간 ∙ 규모 ∙ 종속관계 등 다양한 환경을 고려해서 선택해야 함
- 비동기식 통신이 설정하기 더 복잡하고 더 많은 기술 스택을 사용해야 함
- 하지만 마이크로 서비스에서 더 많은 장점을 갖고 있음
- 비동기식 통신의 장점
- 논블로킹: 기다리지 않고 다른 작업을 수행 가능하니 효율이나 반응 속도가 뛰어남
- 확장성: 동기식 보다 결합도가 떨어지기 때문에 확장성이 좋음
이벤트 브로커
- 이벤트 또는 메시지라고 불리는 정보를 하나만 보관하고 인덱스를 통해 개별 엑세스를 관리
- 업무상 필요한 시간 동안 이벤트를 관리
- 메시지 브로커와 다르게 이벤트가 삭제되지 않는다는 특징 존재
- 서비스에세 발생하는 이벤트를 데이터베이스에 저장하듯이 이벤트 브로커의 큐에 저장
- 이벤트를 저장함으로써 얻는 장점
- 딱 한번 일어난 이벤트 데이터를 브로커에 저장함으로써 모든 데이터 요소를 한 곳에서만 제어 또는 편집하도록 조작하는 관례 ( 단일 진실 공급원 ) 에 맞게 동작
- 장애가 발생했을 때 장애가 일어난 지점부터 재처리 가능
- 많은 양의 실시간 스트림 데이터를 효과적으로 처리 가능
- 이벤트를 받아서 처리하면서 이벤트를 삭제하지 않음
- 손실되면 안되는 요청을 처리할 때 좋음
생산자와 소비자
- 생산자: 데이터를 메시지 큐에 전달하는 입장
- 소비자: 메시지 큐에서 데이터를 가져오는 입장
📮 RabbitMQ
- 메시지 브로커
- 구성이 쉬움
- 복잡한 라우팅을 지원
- 오래되었고 안정성이 높음
- 20K/sec 정도의 속도를 보임
- 소비자 중심의 설계
- 데이터 손실의 위험성
- 성능 문제
- 응용 프로그램 ( applications ) 에게 메시지를 주고 받을 수 있으며 메시지가 수신될 때까지 안전하게 있을 수 있도록 하는 공용 플랫폼 ( common platform ) 을 제공
- 메시지를 다른 대기열로 보낼 수 있는 라우팅 시스템을 갖추고 있음
- 우선 순위가 높은 메시지를 먼저 사용하기 위해 작업자가 사용할 수 있는 메시지의 우선 순위를 지원
- 메시지 브로커로서
Redis
와 비교할 때 훨씬 더 다양한 기능을 제공
- 크고 복잡한 메시지에 적합
RabbitMQ
는 오픈 소스 메시지 브로커 소프트웨어
- 구성
- Producer 는 요청을 보내는 주체
- Consumer 는 생산자로부터 메시지를 받아 처리하는 주체
- Exchange 는 메세지를 전달하고자 하는 목적지(큐)에 전달하는 주체
- Queues 는 메세지를 쌓는 주체
- 메시지 처리 과정
- Producer 가 메세지 보냄
- Exchange 에서 해당하는 키에 맞게 큐에 분배 ( 바인딩 또는 라우팅 )
topic
모드: Routing Key 가 정확히 일치하는 Queue 에 메시지 전송 ( Unicast )
direct
모드: Routing Key 패턴이 일치하는 Queue 에 메시지 전송 ( Multicast )
headers
모드: Key-Value 로 이루어진 header 값을 기준으로 일치하는 Queue 에 메시지 전송 ( Multicast )
fanout
모드: 해당 Exchange 에 등록된 모든 Queue 에 메시지 전송 ( Broadcast )
- 해당 Queue 에서 Consumer 가 메세지를 받음
- 특징
- MQ Server 가 종료 후 재기동 하면 기본적으로 Queue 내용은 모두 제거
RabbitMQ
는 AMQP 를 구현
- AMQP ( Advanced Message Queuing Protocal ) 는 메시지 지향 미들웨어를 위한 개방형 표준 응용 계층 프로토콜
📮 Redis
- 메시지 브로커
- 메모리 기반의 딕셔너리 구조 데이터 관리 시스템
- 처리 속도가 빠름
- 캐시의 역할도 가능
- 명시적으로 데이터 삭제 가능
- 메모리 기반이므로 서버가 다운되면
Redis
내의 모든 데이터가 사라짐
- 디스크에 상주하는 인메모리 데이터베이스
- 컴퓨터 메모리를 이용한 ( in-memory ) Cache 서버
- Key-Value 를 이용해
Celery
가 처리할 작업을 Celery
에게 보낸 후 Cache 에서 해당 Key 를 제거하는 방식으로 작동
Redis
는 데이터 검색을 위해 데이터베이스에 접근하기 전 메모리에서 Cache 를 가져다 쓴다는 점에서 속도가 빠름
- 매우 빠른 서비스 및 메모리 내 기능을 제공하기 때문에 지속성이 중요하지 않고 약간의 손실을 견딜 수 있는 짧은 보존 메시지에 적합
- 큰 메시지를 처리할 때는 대기 시간이 오래 걸림
- Key-Value 구조의 비정형 데이터를 저장하는 비관계형 데이터베이스 관리 시스템
- 캐시 역할로 많이 사용
- 사용자가 많은 서비스에서 데이터베이스가 과부하될 때 캐시 역할로 많이 사용됨
- Single Threaded 기반으로 운영
- 구성 요소
- Publisher 는 메세지를 게시 ( Pub )
- Channel 은 메세지를 쌓아두는 Queue
- Subscriber 는 메세지를 구독 ( Sub )
- 동작
- Publisher 가 Channel 에 메세지 게시
- 해당 채널을 구독하고 있는 Subscriber 가 메세지를 Sub 해서 처리함
- 특징
- Channel 은 이벤트를 저장하지 않음
- Channel 에 이벤트가 도착했을 때 해당 채널의 Subscriber 가 존재하지 않는다면 이벤트 사라짐
- Subscriber 는 동시에 여러 채널을 구독할 수 있으며 특정한 채널을 지정하지 않고 패턴을 설정하여 해당 패턴에 맞는 채널을 구독할 수 있음
📮 Kafka
- 이벤트 브로커
- 구독 방식의 비동기식 구성
- 분산 처리에 효과적
- 생산자 중심의 설계
- 이벤트 기반 마이크로 서비스 아키텍쳐로 발전하는데 큰 도움이 될 수 있음
- 100K/sec 정도의 속도
- 아파치 소프트웨어 재단이 스칼라로 개발한 오픈 소스 메시지 브로커 프로젝트
- 개념
- Pub/Sub 모델의 메세지 큐
- 분산 환경에 특화되어 있는 특징
RabbitMQ
와 같은 다른 메시지 큐보다 빠름
- 클러스터 구성 ∙ Fail-Over ∙ Replication 과 같은 기능 존재
- 구성 요소
- Event 는
kafka
에서 Producer 와 Consumer 가 데이터를 주고받는 단위 (=메시지)
- Producer 는
kafka
에 이벤트를 게시 ( POST
∙ POP
) 하는 클라이언트 어플리케이션
- Consumer 는 Topic 을 구독하고 이로부터 얻어낸 이벤트를 받아 ( Sub ) 처리하는 클라이언트 어플리케이션
- Topic 은 이벤트가 모이는 곳
- Producer 는 Topic 에 이벤트를 게시하고 Consumer 는 Topic 을 구독해 이로부터 이벤트를 가져와 처리
- 게시판 같은 개념
- Topic 은 여러 Broker 에 분산되어 저장되는데 이렇게 분산된 Topic 을 Partition 이라고 함
- Zookeeper 는 분산 메시지의 큐의 정보를 관리
- 하나의 토픽에 여러 개의 파티션을 나눠서 이벤트 (=메시지) 를 쓰는 이유
kafka
의 토픽에 메세지가 쓰여지는 것도 어느 정도 시간이 소비됨
- 몇 천건의 메세지가 동시에
kafka
에 write
되면 병목 현상이 발생할 수 있음
- 따라서 파티션을 여러개 두어서 분산 저장함으로써
write
동작을 병렬로 처리할 수 있음
- 다만 한 번 늘린 파티션은 절대 줄일 수 없기 때문에 운영 중에 파티션을 늘려야 하는건 충분히 고려해서 실행해야 함
- 파티션을 늘렸을 때 메세지가
round-robin
방식으로 쓰여짐
- Fail-Over 시 마지막 위치부터 다시 메세지를 불러올 수 있음
- 각 파티현에 존재하는
offset
의 위치를 통해 이전에 소비했던 offset
위치를 기억하고 관리
- 따라서 Consumer 가 죽었다가 다시 살아나도 전에 마지막으로 읽었던 위치에서부터 다시 읽어들일 수 있음
- Consumer 그룹이 존재하는 이유
- Consumer 의 묶음을 Consumer Group 이라고 함
- Consumer Group 은 하나의 토픽에 대한 책임을 가지고 있음
- 즉 어떤 Consumer 가 다운된다면 파티션 재조정 ( 리밸런싱 ) 을 통해 다른 Consumer 가 해당 파티션의 Sub 를 맡아서 함
offset
정보를 그룹 간에 공유하고 있기 때문에 다운되기 전 마지막으로 읽었던 메세지 위치부터 시작
Tip! 추가 내용
Tip! 추가 내용
Celery
Celery
는 Python 으로 작성된 분산 메시지 전달을 기반으로 한 비동기 작업 큐로 Worker 의 한 종류
- 요청을 받은 뷰에서는 Broker 에게 해당 작업 실행을 위임하고 각 작업을 구분할 수 있는 Task ID 를 발급받게 됨
- 해당 작업은 Broker 가 놀고 있는 Worker 에게 넘겨서 Worker 가 비동기로 수행하도록 함
- Django 서버에서 Task 를 메시지 브로커를 통해 전달을 하면 하나 이상의
Celery
Worker 가 메시지 브로커 큐에 있는 Task 를 받아서 이를 관리