Kafka란?
Event-driven 방식
https://jaehun2841.github.io/2019/06/23/2019-06-23-event-driven-architecture/#Event-Driven-%EB%9E%80
메시지 큐(Message Queue)
메시지 큐(Message Queue 이하 MQ)란 프로세스(프로그램) 간에 데이터를 교환할 때 사용하는 통신 방법
더 큰 개념으로는 MOM(Message Oriented Middleware : 메시지 지향 미들웨어 이하 MOM)를 의미한다.
MOM이란 비동기 메시지를 사용하는 프로그램 간의 데이터 송수신을 의미하는데 MOM을 구현한 시스템을 MQ라고 한다.
메시지 큐의 장점
- 비동기 : Queue에 넣기 때문에 나중에 처리할 수 있음.
- 비동조 : Application과 분리할 수 있음.
- 탄력성 : 일부가 실패 시 전체는 영향을 받지 않는다.
- 과잉 : 실패할 경우 재실행이 가능.
- 확장성 : 다수의 프로세스들이 큐에 메시지를 보낼 수 있다.
사용하는 이유와 사용처
애플리케이션/시스템 간의 통신
서버 간에 데이터를 주고 받거나 어떤 작업을 요청을 할 때는 항상 시스템 장애를 염두에 두어야 한다.
서버가 갑자기 죽거나 서버 점검 등으로 다운타임이 발생하는 동안에는 요청을 보낼 수가 없다.
요청하는 서버에서 failover 처리를 해놓고 연계 시스템이 다시 살아났을 때 요청을 보내는 방법도 있지만 MQ를 이용하면 더욱 간편하게 처리할 수 있다.
P는 C에 직접 요청하는 것이 아닌 MQ에 전달한다.
그럼 C는 MQ로 부터 요청 데이터를 수신해서 처리한다.
만약 C가 요청을 받을 수 없을 수 없는 상황이라면 해당 요청은 C가 받을 때까지 MQ에 머무르게 된다.
물론 이런 상황에서 MQ에 다운타임이 발생하면 무용지물이 되어버리겠지만, 많은 MQ가 고가용성을 위해 클러스터링 등을 지원한다.
서버 부하가 많은 작업
이미지 처리, 비디오 인코딩, 대용량 데이터 처리와 같은 작업은 메모리와 CPU를 많이 사용한다.
이러한 작업은 동시에 처리할 수 있는 양이 상당히 한정적이어서 필요하다고 무작정 요청을 처리할 수는 없다.
이 때에도 MQ를 사용하면 편리한데 처리해야할 작업을 MQ에 넣어두고 서버는 자신이 동시에 처리할 수 있는 양에 따라 하나의 작업이 끝나면,
다음에 처리할 작업을 MQ에서 가져와 처리하면 된다.
부하분산
MQ를 통해 부하분산 처리도 가능하다. 지금까지 설명은 하나의 서버에 대해서만 설명했다.
그림처럼 여러 대의 서버가 하나의 큐를 바라보도록 구성하면 처리할 데이터가 많아져도 각 서버는 자신의 처리량에 맞게 태스크를 가져와 처리할 수 있다.
이러한 구조는 horizontal scaling에 유리하다.
데이터 손실 방지
MQ를 사용하지 않는다면 외부에서 받은 요청을 메모리에 저장했다가 들어온 순서대로 처리하게 할 수도 있다.
하지만 어떠한 이유로 서버가 다운되어 버리면 메모리에 쌓아둔 요청은 모두 없어지고 만다.
MQ를 사용하면 이를 방지할 수 있는데 MQ로부터 가져온 태스크를 일정 시간이 지나도록 처리했다고 다시 MQ에 알려주지 않으면 MQ는 이 태스크를 다시 큐에 넣어 다시 처리할 수 있도록 한다.
MQ를 사용할 때 얻을 수 있는 잇점은 많지만 적재적소에 사용해야 한다. 요청 결과를 즉시 응답해야할 때에는 MQ는 어울리지 않는다. 주로 요청과는 별개로 처리할 수 있는 비동기 처리에 어울린다. 또한 서버에서 간단하게 처리할 수 있는 일을 MQ를 통해 전달하면 필요없는 오버헤드될 수도 있다.
MQ 대표 솔루션
공통 특징
- 다른 곳의 API로부터 데이터 송수신
- 다양한 Application에서 비동기 통신 가능
- 이메일 발송 및 문서 업로드 가능
- 많은 양의 프로세스 처리
- 메시지 큐 종류
대표적인 종류
- Kafka
- RabbitMQ
- ActiveMQ
성격상 Kafka(Apache)와 RabbitMQ, ActiveMQ(Apache)로 나눌 수 있는데
Kafka는 처리량이 많은 분산 메시징 시스템에 적합하고
RabbitMQ, ActiveMQ는 신뢰성 있는 메시지 브로커가 필요한 경우 적합하다.
여기서 신뢰성은 Kafka에 비해 높은 것이지 Kafka가 신뢰성이 없다는 것은 아니다.
🔥 Apache Kafka
카프카는 크게 프로듀서, 카프카(브로커), 컨슈머, 주키퍼로 분류할 수 있다.
- 프로듀서 : 카프카와 통신하면서 메시지를 보내는 역할
- 컨슈머 : 카프카와 통신하면서 메시지를 가져오는 역할
- 주키퍼 : 컨슈머와 통신, 카프카의 메타데이터 정보를 저장, 카프카의 상태관리 등 목적으로 이용
- 카프카
출처: https://cornswrold.tistory.com/523 [평범한개발자노트] - 특징
- 카프카는 지향하는 바가 다른 메시지 큐와 다르다
- 실시간 데이터 피드를 관리하기 위한 플랫폼을 제공하는 것이 목표
- pub-sub 구조를 가진다.
- 메시지를 보내는 역할과 받는 역할이 완벽하게 분리되어 있다.
- 느슨한 결합을 통해 어느 한쪽 시스템에서 문제가 발생하더라도 서로 의존성이 없으므로 연쇄작용이 발생할 확률은 매우 낮다.
- 하나의 토픽에 여러 프로듀서 또는 컨슈머들이 접근 가능한 구조로 되어 있다.
- 하나의 프로듀서, 컨슈머가 하나의 토픽에만 메시지를 보내는 것이 아니라, 하나 또는 하나 이상의 토픽으로 메시지를 보낼 수, 가져올 수 있다.
- 디스크에 메시지를 저장
- 다른 메시지큐와의 가장 큰 차이점은 통신할 때 TCP/IP 통신을 통해 바로 디스크로 쓴다는점.
- 별다른 설정 없이도 데이터의 영속성 보장
- 디스크가 순차적으로 저장되어 있으므로 디스크 I/O가 줄어들어 성능이 빨라짐.
- 분산 환경에 특화되도록 설계
- 하나의 카프카 클러스터는 3대의 브로커로 부터 시작해 수십대의 브로커로 확장 가능
- 확장 작업은 카프카 서버의 중단없이 온라인 상태에서 작업 가능
- 최초 카프카 클러스터 구성시 적은 수로 시작하더라도 이후 트래픽 및 사용량 증가로 클러스터를 확장하는 작업은 매우 간단.
- 카프카는 고성능을 유지하기 위해 내부적으로 분산 처리, 배치 처리등 다양한 기법 사용
- 클러스터 구조의 분산 시스템은 단일 시스템보다 성능이 좋다.
구조와 주요 용어
Topic, Partitions, Offsets
- topic : 메시지 종류, 특정한 데이터 스트림을 의미
- 토픽의 개수는 제한이 없고, 이름으로 구분
- 토픽이 다시 특정한 개수의 partitions이 됨. 개수의 명시가 필요
- partitions : topic이 나눠지는 단계
- 유한한 시간(default oneweek)동안 디스크에 저장되어 있다.
- 파티션에 한 번 쓰여진 데이터는 변경이 불가능
- 토픽을 구성하는 파티션은 정렬되어 있지만, 쓰여지는 데이터는 키 값이 제공되지 않으면 파티션에 랜덤하게 할당
- 각 파티션 속 메시지는 오름차순의 id값인 offset을 가지고 있다.
- offset : 속해 있는 파티션에서만 의미 있는 값, 파티션 내에서 각 메시지가 가지는 unique id
- 순서는 속해 있는 파티션에서만 보장 -> 다른 파티션에서 동일한 offset이 가리키는 데이터는 같지 않다.
Broker
- broker : 카프카 서버를 가르킴. 카프카 클러스터는 1개 이상의 브로커로 구성됨.
- 각 브로커는 정수형 ID 값으로 구분되며 특정한 토픽의 파티션을 보유
- 브로커끼리 연결하면 클러스터가 되며, 3개 이상을 가지는 것이 장애 허용 관점에서 좋다
- 토픽을 생성하면 카프카가 자동적으로 파티션들을 브로커에 분배
Producer, Consumer
producer : 메세지 발행자, 기본적으로 카프카에서 프로듀서는 토픽에 데이터를 쓰는 객체
- producer는 선택한 topic으로 데이터를 발행
- producer는 메세지를 발행할 topic을 선택하는 책임을 지게 됨.
- 이 때 전통적이 round-robin방식을 사용하여 균등하게 발행하거나 메세지 키를 이용하여 특정 파티션에 특정 키를 가진 메시지를 보낼 수 있다.
- 어떤 브로커의 파티션에 저장해야하는지 자동으로 저장 위치를 안다. 장애 발생시 자동 회복이 됨. 기본적인 로드 밸런싱이 되어있음
- 메세지에 문자열이나 숫자 등의 키 값을 포함해서 메세지를 보낼 수 있다.
- 데이터 저장 성공 여부를 acks를 통해 확인할 수 있다.
- 키 값이 없으면 데이터는 라운드 로빈 방식으로 브로커에 전송(로드 밸런싱)
- 키 값이 있으면 메세지는 (키 해싱에 의한)하나의 파티션에만 지속적으로 전달
Consumer : 메세지 소비자 , 토빅으로부터 데이터를 읽어드림
- 데이터는 각 파티션에 들어온 순서대로 읽힌다.
- 읽어 들이는 파티션 순서는 정해져 있지 않고, 돌아가면서 병렬처리 된다. -> 파티션 순서에 대한 보장이 없다.
Broker Discovery, Zookeeper
- 모든 카프카 브로커는 "부트스트랩 서버" 라 불린다.
- 다른 브로커 하나와만 연결해도 전체 클러스터에 연결이 되며, 각각의 브로커는 전체 브로커와 토픽들 그리고 파티션들에 대한 정보(메타데이터)를 알고 있다.
Zookeeper: 카프카 서버 (+클러스터) 상태를 관리 -> 분산 코디네이터다.
- 브로커를 모니터링하고, 토픽과 파티션을 관리한다.
- 주키퍼는 카프카 클러스터 내의 브로커들의 리스트를 가지고 있으며 브로커들을 관리하며 카프카는 주키퍼 없이 실행할 수 없다.
- 리더 파티션에 장애가 발생시 주키퍼를 통해 새로운 리더 파티션을 선발한다.
- 새로운 토픽 추가, 브로커 장애 및 토픽 삭제 등의 변경 정보를 카프카에 전달한다.
- 주키퍼는 홀수 개의 서버(3,5,7 ...)를 가지고 있어야 한다.
- 주키퍼는 쓰기를 관장하는 리더 서버 1개와 읽기를 관장하는 나머지 팔로워 서버로 구성된다
'Study > Kafka' 카테고리의 다른 글
Kafka Topic (0) | 2023.12.07 |
---|---|
Kafka 고가용성(HA)의 핵심 - Broker, Replication, ISR (2) | 2023.11.30 |
kafka, zookeeper properties file 작성법 (1) | 2023.11.30 |
Kafka 커맨드 라인 명령어 (0) | 2023.11.30 |
Kafka 설치와 Spring Boot 연동 (0) | 2023.11.29 |
댓글