대표적인 "이벤트 브로커" 카프카의 원리를 좀 더 자세하게 살펴보자. 메시지 브로커에 역할에 좀 더 집중한다.
메시지 브로커는 publisher가 생산한 메시지를 메시지 큐에 저장하고, 저장된 데이터를 consumer가 가져갈 수 있도록 "중간 다리 역할"을 해주는 브로커(broker)다. 흔히 S/W 관점에서 "미들웨어"라고 한다.
보통 서로 다른 시스템(혹은 소프트웨어 / 이기종간) 사이에서 데이터를 비동기 형태로 처리하기 위해 사용한다.
이러한 구조를 보통 pub/sub 구조라고 하며 대표적으로 RabbitMQ 소프트웨어가 있고 GCP의 pubsub, AWS의 SQS 같은 서비스가 있다.
이와 같은 메시지 브로커들은 consumer가 큐에서 데이터를 가져가게 되면 즉시 혹은 짧은 시간 내에 큐에서 데이터가 삭제되는 특징이 있다.
이벤트 브로커 또한 기본적으로 메시지 브로커의 큐 기능들을 가지고 있어 메시지 브로커의 역할도 할 수 있다. 가장 중요한 차이는 이벤트 브로커는 메시지 브로커 역할을 할 수 있지만, 메시지 브로커는 이벤트 브로커 역할을 할 수 없다.
또한 이벤트 브로커는 publisher가 생산한 이벤트를 저장하여, 후에 consumer가 특정 시점부터 이벤트를 다시 consume 할 수 있는 장점이 있다. (예를 들어 "장애가 일어난 시점부터 그 이후의 이벤트들을 다시 처리" 할 수 있다.)
대용량 데이터 처리에 있어서 메시지 브로커보다는 더 많은 양의 데이터를 처리할 수 있는 능력이 있다.
메시지 큐(Message Queue
이하 MQ)란 프로세스(프로그램) 간에 데이터를 교환할 때 사용하는 통신 방법 중에 하나로 더 큰 개념으로는 MOM(Message Oriented Middleware : 메시지 지향 미들웨어 이하 MOM)를 의미한다. MOM이란 비동기 메시지를 사용하는 프로그램 간의 데이터 송수신을 의미하는데 MOM을 구현한 시스템을 MQ라고 한다. MQ는 작업을 늦출 수 있는 유연성을 제공한다.
Advanced Message Queuing Protocol
이하 AMQP)을 이용한다. AMQP는 ISO 응용 계층의 MOM 표준으로 JMS(Java Message Service)와 비교되는데 JMS는 MOM를 자바에서 지원하는 표준 API다. JMS는 다른 Java Application 간에 통신은 가능하지만 다른 MOM(AMQP, SMTP 등)끼리는 통신할 수 없다. 그에 반해 AMQP는 protocol만 일치한다면 다른 AMQP를 사용한 Application과도 통신이 가능하다. AMQP는 wire-protocol을 제공하는데 이는 octet stream을 이용해서 다른 네트워크 사이에 데이터를 전송할 수 있는 포맷이다.(출처: rabbitmq.com)
P는 C에 직접 요청하는 것이 아닌 MQ에 전달한다. 그럼 C는 MQ로 부터 요청 데이터를 수신해서 처리한다. 만약 C가 요청을 받을 수 없을 수 없는 상황이라면 해당 요청은 C가 받을 때까지 MQ에 머무르게 된다.
물론 이런 상황에서 MQ에 다운타임이 발생하면 무용지물이 되어버리겠지만, 많은 MQ가 고가용성을 위해 클러스터링 등을 지원한다.
(출처: rabbitmq.com)
(메시지 브로커 역할로만 봤을 땐) 성격상 Kafka(Apache) 와 RabbitMQ, ActiveMQ(Apache) 로 나눌 수 있는데 Kafka는 처리량이 많은 분산 메시징 시스템에 적합하고 RabbitMQ, ActiveMQ는 신뢰성 있는 메시지 브로커가 필요한 경우 적합하다. 여기서 신뢰성은 Kafka에 비해 높은 것이지 Kafka가 신뢰성이 없다는 것은 아니다.
메시지를 보내는 역할과 받는 역할이 완벽하게 분리되어 있다.
느슨한 결합을 통해 어느 한쪽 시스템에서 문제가 발생하더라도 서로 의존성이 없으므로 연쇄작용이 발생할 확률은 매우 낮다.
컨슈머의 서버가 하나더 추가 되더라도 카프카로만 보내면 되기 때문에 서버 추가에 대한 부담도 줄일 수 있다.
하나의 토픽에 여러 프로듀서 또는 컨슈머들이 접근 가능한 구조로 되어 있다. 그렇기 때문에 하나의 프로듀서, 컨슈머가 하나의 토픽에만 메시지를 보내는 것이 아니라, 하나 또는 하나 이상의 토픽으로 메시지를 보낼 수, 가져올 수 있다.
파티션 파일에 대해서 OS 페이지캐시를 사용한다. -> 파티션에 대한 FILE IO 를 메모리단에서 처리하게 된다. 디스크 버퍼에서 네트워크 버퍼로 직접 데이터 복사하여 처리하게 된다.
다른 message quque 의 가장큰 차이점은 통신할때 TCP/IP통신을 통해 바로 디스크로 쓴다는 점이다. (Rabbit MQ의 경우 APMQ 프로토콜 이용) 다른 MessageQueue도 메모리에만 올리지않고 설정을 통해 서버가 다운되더라도 디스크에 저장하는 설정을 할 수 있다. 카프카는 별도의 설정 없이 디스크에 적재하며, 환경설정에서 그주기를 변경 할 수 있다. 통신방법의 차이로 인해 (TCP/IP, APMQ) 카프카는 초당 10만건, Rabbit MQ는 초당 2만건의 데이터 처리가 가능하다.
별다른 설정 없이도 데이터의 영속성(Persistence)가 보장된다는 것을 의미한다.
트래픽이 일시적으로 폭주해 컨슈머의 처리가 늦어지더라도 카프카의 디스크에 안전하게 보관되어 있기 때문에, 컨슈머는 메시지의 손실 없이 메시지를 가져갈 수 있다.
디스크가 순차적으로 저장되어 있으므로 디스크 I/O가 줄어들어 성능이 빨라진다.
하나의 카프카 클러스터는 3대의 브로커로 부터 시작해 수십대의 브로커로 확장 가능하다.
확장 작업은 카프카 서비스의 중단 없이 온라인 상태에서 작업이 가능하다.
최초 카프카 클러스터 구성시 적은 수로 시작하더라도 이후 트래픽 및 사용량 증가로 클러스터를 확장하는 작업은 매우 간단하고, 큰 부담이 없다.
카프카는 고성능을 유지하기 위해 내부적으로 분산 처리, 배치 처리 등 다양한 기법을 사용한다.
클러스터 구조의 분산 시스템은 단일 시스템보다 성능이 좋다.
topic
: 메세지 종류, 특정한 데이터 스트림을 의미한다.
partitions
: topic
이 나눠지는 단위다.
offsets
: 속해 있는 파티션에서만 의미 있는 값, 파티션 내에서 각 메시지가 가지는 unique id
broker
: 카프카 서버를 가리킨다. 카프카 클러스터는 1개 이상의 브로커(서버)로 구성된다!브로커 설명 그림과 같이 분산 처리를 하게 될 때 하나의 브로커에 장애가 발생해도 시스템이 정상적으로 운영되게 하기 위해 다른 브로커에 레플리케이션(복사본)을 만들어두는 것이 안정적이다. 위 그림은 레플리케이션이 3개인 토픽이 브로커가 3개인 클러스터에 각 파티션이 분산되어 있는 예시이다.
토픽은 replication
의 개수가 1개 보다는 커야 좋고, 브로커가 다운되면 다른 브로커가 데이터를 처리해준다.
레플리케이션 정책에서 오직 하나의 브로커만이 주어진 파티션 복사본들의 리더가 될 수 있다. 그리고 오직 이 리더 하나만 데이터를 받고 처리하는 파티션이 된다.
다른 브로커들은 데이터를 동기화한다. 각 파티션은 하나의 리더와 다수의 ISR(In-Sync Replica)이 있다
producer
: 메세지 생산(발행)자. 기본적으로 kafka에서 프로듀서는 토픽에 데이터를 쓰는 개체이다. 특정한 데이터 필드에 대한 요청이 필요하면 키를 활용
consumer
: 메세지 소비자, 토픽으로부터 데이터를 읽어들인다.
데이터는 각 파티션에 들어온 순서대로 읽힌다.
읽어 들이는 파티션 순서는 정해져 있지 않고, 돌아가면서 병렬처리 된다. -> 파티션 순서에 대한 보장이 없다.
consumer group
: 개별 컨슈머들을 하나로 묶은 논리적 그룹 단위, consumer 들끼리 메세지를 나눠서 가져간다. offset 을 공유하여 중복으로 가져가지 않는다.
그룹 내 특정 컨슈머에 장애가 생겨도 다른 컨슈머들이 데이터를 읽을 수 있다.
컨슈머 그룹내 컨슈머가 파티션 숫자보다 많으면 비활성화되는 컨슈머가 발생한다. -> 컨슈머와 파티션 개수를 잘 조절해야 한다.
위와 같은 "기록 시점 관련"해서는 아래와 같은 3가지 정책이 있다.
1) At most once(비선호)
컨슈머가 메세지를 받는 순간 기록
처리가 잘못되어도 메세지는 이미 삭제되어 있다(데이터 손실)
2) At least once(선호)
메세지를 받은 컨슈머가 데이터를 처리하는 순간 기록
프로세스가 잘못되면 메세지를 다시 읽어드린다
데이터 중복 처리가 발생해도 시스템에 문제가 없는 프로세스에만 적용
3) Exactly once
카프카 생태계(카프카->카프카)에서 가능(Kafka Stream API 등)
외부 시스템과의 연결을 할 때는 연산을 여러번해도 결과가 달라지지 않는 컨슈머만 가능(멱등 시스템)
모든 카프카 브로커는 "부트스트랩 서버" 라 불린다.
다른 브로커 하나와만 연결해도 전체 클러스터에 연결이 되며, 각각의 브로커는 전체 브로커와 토픽들 그리고 파티션들에 대한 정보(메타데이터)를 알고 있다.
Zookeeper: 카프카 서버 (+클러스터) 상태를 관리 -> 분산 코디네이터다.
ksql
: Kafka를 위한 streaming SQL 이다.kafka topic ui
: topic 정보를 확인 할 수 있는 kafaka topic uiZooNavigator
: 주키퍼 정보를 웹으로 네비게이션하고 편집 할 수 있다.