2장. 카프카 기초

문법식·2022년 8월 10일
0

카프카의 송수신 구조와 카프카의 기본 용어를 배운다. 주요 내용은 다음과 같다.

  • 메시지 송수신 기본
  • 시스템 구성
  • 분산 메시징을 위한 구조
  • 데이터 견고함을 담보하는 복제의 구조

메시지 송수신 기본

카프카의 주요 구성 요소는 다음 5가지다.

  • 브로커
    - 데이터를 수신, 전달하는 서비스
  • 메시지
    - 카프카에서 다루는 데이터의 최소 단위. 카프카가 중계하는 로그의 한 줄 한 줄과 센서 데이터 등이 이에 해당. 메시지는 KeyValue를 갖게 되며 메시지 전송 시 파티셔닝에 활용
  • 프로듀서
    - 데이터의 생산자이며 브로커에 메시지를 보내는 애플리케이션
  • 컨슈머
    - 브로커에서 메시지를 취득하는 애플리케이션
  • 토픽
    - 메시지를 종류(토픽)별로 관리하는 스토리지. 브러커에 배치되어 관리된다. 프로듀서와 컨슈머는 특정 토픽을 지정하여 메시지를 송수신함으로써 단일 카프카 클러스터에 여러 종류의 메시지를 중계한다.

시스템 구성

위에서 각 구성 요소의 논리 구성에 대해 설명했다. 각 구성 요소를 동작시키는 데 필요한 시스템 구성을 알아본다.

브로커

브로커는 하나의 서버(또는 인스턴스) 당 하나의 데몬 프로세스로 동작하여 메시지 수신/전달 요청을 받아들인다. 이것을 여러 대의 클러스터로 구성할 수 있으며 브로커(리소스)를 추가함으로써 수신/전달의 처리량 향상(스케일 아웃)이 가능하다.
브로커에서 받은 데이터는 모두 디스크로 내보내기(영속화)가 이루어져 디스크의 총 용량에 따라 장기간 데이터를 보존할 수 있다.

프로듀서 API/컨슈머 API

프로듀서/컨슈머를 구현하는 기능은 브로커로 데이터를 보내고 브로커에서 데이터를 받기 위한 라이브러리로 제공된다. 프로듀서와 컨슈머를 구현하기 위한 API를 프로듀서 API/컨슈머 API라 한다. 프로듀서, 컨슈머는 브로커처럼 데몬 프로세스로 작동하는 프로그램이 아니다. API는 자바로 제공된다.

프로듀서

프로듀서는 프로듀서 API를 이용하여 브로커에 데이터를 송신하기 위해 구현된 애플리케이션이다. 실제 사례로는 각종 로그 전송 및 미들웨어와 연동하여 동작하기 때문에 프로듀서 API를 내포한 도구, 미들웨어를 통해 이용하는 형태 등 다양하다.

컨슈머

컨슈머 API를 이용해 브로커에서 메시지를 취득하도록 구현된 애플리케이션이다. 브로커는 메시지를 영속화하기 떄문에 브로커에 메시지가 도달하는 즉시 컨슈머에서 취득해야 하는 제약이 없어 디스크에 보관되어 있는 동안은 메시지 취득이 가능하다. 일정 기간 데이터를 축적한 스토리지에서의 데이터 추출 및 실시간 처리를 위한 애플리케이션의 데이터 입력 등으로 이용된다.

주키퍼

카프카의 브로커에 있어 분산 처리를 위한 관리 도구로 아파치 주키퍼가 필요하다. 주키퍼는 하둡 등 병렬 분산 처리용 OSS에 있어서 설정 관리, 이름 관리, 동기화를 위한 잠금 관리를 하는 구조로 자주 사용된다. 카프카에 있어서는 분산 메시징의 메타 데이터(토픽과 파티션)를 관리하기 위한 구성 요소로 기능한다. 주키퍼 클러스터(주키퍼 앙상블)의 구조상 3, 5처럼 홀수로 구성하는 것이 일반적이다.

카프카 클라이언트

토픽 작성 등 카프카의 동작 및 운영 상에 필요한 조작을 실행하는 서버다.

카프카 클러스터

카프카는 여러 대의 브로커 서버, 주키퍼 서버로 이루어진 클러스터링의 메시지 중계 기능과 송수신을 위한 라이브러리 그룹으로 구성된다. 이 책에서는 전자의 브로커, 주키퍼에 의해 구성된 클러스터 시스템을 카프카 클러스터라고 정의한다.


분산 메시징을 위한 구조

파티션

토픽에 대한 대량의 메시지 입출력을 지원하기 위해, 브로커상의 데이터를읽고 쓰는 것은 파티션이라는 단위로 분할되어 있다. 토픽을 구성하는 파티션은 브로커 클러스터 안에 분산 배치되어 프로듀서에서의 메시지 수신, 컨슈머로의 전달을 분산해서 실시함으로써 하나의 토픽에 대한 대규모 데이터 수신과 전달을 지원한다.
각 파티션을 어떻게 배치하는가에 대한 정보는 브로커 측에 유지된다. 또한 프로듀서 API/컨슈머 API가 파티션들을 은폐해서 통신하기 때문에 프로듀서/컨슈머는 토픽만을 지정하고, 구현 시에 송신처 파티션을 신경쓰지 않아도 된다.(추상화했다는 뜻으로 이해했다.)

컨슈머 그룹

카프카는 컨슈머에서 분산 스트림 처리도 고려해 설계되어 있다. 단일 애플리케이션 안에서 여러 컨슈머가 단일 토픽이나 여러 파티션에서 메시지를 취득하는 방법으로 컨슈머 그룹이라는 개념이 있다.
카프카 클러스터 전체에서 글로벌 ID를 컨슈머 그룹 전체에서 공유하고 여러 컨슈머는 자신이 소속한 컨슈머 그룹을 식별해, 읽어들일 파티션을 분류하고 재시도를 제어한다.

오프셋

각 파티션에서 수신한 메시지에는 각각 일련번호가 부여되어 있어 파티션 단위로 메시지 위치를 나타내는 오프셋이라는 관리 정보를 이용해 컨슈머가 취득하는 메시지의 범위 및 재시도를 제어한다. 제어에 사용되는 오프셋의 종류는 다음과 같다.

  • Log-End-Offset(LEO): 파티션 데이터의 끝을 나타낸다.
  • Current Offset: 컨슈머가 어디까지 메시지를 읽었는가를 나타낸다.
  • Commit Offset: 컨슈머가 어디까지 커밋했는지를 나타낸다.

LEO는 브로커에 의해 파티션에 관한 정보로 관리 및 업데이트된다. Commit Offset은 컨슈머 그룹마다 보관되어 관리, 업데이트 된다.
Current Offset은 컨슈머에서의 데이터 취득을 계기로 업데이트된다. Commit Offset은 컨슈머로부터 '여기까지의 오프셋은 처리했다'라는 것을 확인하는 오프셋 커밋 요청을 계기로 업데이트된다. 특정 토픽에 대해 여러 컨슈머 그룹이 메시지를 취득하는 경우는 파티션에 대한 Commit Offset도 컨슈머 그룹 숫자만큼만 존재한다.

메시지 송수신

카프카에서 메시지 송신은 반드시 하나하나의 메시지 단위로 송수신하는 것이 아니다. 송수신 처리량을 높이기 위해 어느 정도 메시지를 축적하여 배치 처리로 송수신하는 기능 또한 제공한다.

프로듀서의 메시지 송신

프로듀서가 토픽의 파티션에 메시지를 송신할 때 버퍼 기능처럼 프로듀서의 메모리를 이용하여 일정량을 축적 후 송신할 수 있다. 데이터의 송신에 대해서는 지정한 크기까지 메시지가 축적되거나, 지정한 대기 시간에 도달하는 것 중 하나를 트리거로 전송한다.
기본 설정으로 하나의 메시지는 1회 송신되지만, 용량이 작은 메시지를 대량으로 브로커에 송시하는 상황에서는 네트워크의 지연이 처리량에 영향을 주는 경우도 있어 메시지를 배치로 송신함으로써 처리량을 향상시킨다.

컨슈머의 메시지 취득

컨슈머는 취득 대상의 토픽과 파티션에 대해 Current Offset으로 나타나는 위치에서 마지막으로 취득한 메시지부터 브로커에서 보관하는 최신 메시지까지 모아서 요청 및 취득을 실시하고, 그것을 반복함으로써 계속적인 메시지 취득을 반복한다.'

컨슈머의 롤백

컨슈머는 위에서 언급한 바와 같이 오프셋을 진행하면서 지속적으로 메시지를 취득하지만, Offset Commit의 구조를 이용해 컨슈머 처리 실패, 고장 시 롤백 메시지 재취득을 실현한다.
주의할 점은 Commit Offset까지 되돌아온 오프셋 간 메시지에 대한 대처는 후속 애플리케이션에게 맡긴다는 점이다. 메시지가 재전송되어 중복 처리가 필요한 경우 후속 애플리케이션이 처리한다는 뜻이다. 이 재시도는 Exatly Once가 아니라 At Least Once로 송신하는 구조다. 또한 고장 감지, 복구에 대해서도 카프카에서 제공되는 것은 아니기 때문에 컨슈머 API를 이용한 애플리케이션 쪽에서의 대처가 필요하다. 다행히도 Spark Streaming 등 카프카 연계 기능으 제공하는 대부분의 분산 처리 프레임워크는 컨슈머의 고장이나 장애를 감지하여 재실행하는 메커니즘이 있으므로 일반 사용자가 감지하여 재실행하는 경우는 드물다.

메시지 전송 시 파티셔닝

프로듀서에서 송신하는 메시지를 어떻게 파티션으로 보낼지 결정하는 파티셔닝 기능이 제공되고 있다.
보내는 메시지에 포함된 Key의 명시적인 지정 여뷰에 따라 다음 두 가지 패턴 로직으로 송신된다.

  • key의 해시 값을 사용한 송신
  • 라운드 로빈에 의한 송신

파티셔닝을 이용하는 경우는 데이터 편차에 따라 파티션의 편향에도 주의를 기울여야 한다. 극단적인경우 준비한 파티션 수에 대해 출현하는 Key의 종류가 충분하지 않을 때는 파티션에 편향일 발생하여 리소스를 부분적으로 사용할 수 없는 상태가 된다.


데이터의 견고성을 높이는 복제 구조

카프카는 메시지를 중계함과 동시에 서버가 고장났을 대에 수신한 메시즈를 잃지 않기 위해 복제 구조를 갖추고 있다.
파티션은 단일 또는 여러 개의 레플리카로 구성되어 토픽 단위로 레플리카 수를 지정할 수 있다. 또한 레플리카 중 하나는 Leader이며, 나머지는 Follower라 불린다. FollowerLeader로부터 메시지를 계속적으로 취득하여 복제를 유지하도록 동작한다. 다만 프로듀서/컨슈머와의 데이터 교환은 Leader가 맡고 있다.

레플리카의 동기 상태

Leader Replica의 복제 상태를 유지하고 있는 레플리카는 In-Sync Replica로 분류된다. In-Sync ReplicaISR로 표기되는 경우도 있다. 모든 레플리카가 ISR로 되어 잇지 않은 파티션을 Under Replicated Partitions라고 부른다. 또한 복제 수와는 독립적으로 최소 ISR 수 설정이 가능하며, 고장 등으로 인한 일시적인 동기 지연을 허용하여 전체 읽고 쓰기를 계속하는 것이 가능하다.

복제 완료 최신 오프셋(High Watermark)

복제 사용 시 오프셋 관리에는 LEO 이외에 High Watermark라는 개념이 있다. High Watermark는 복제가 완료된 오프셋이며, 그 성질에서 반드시 LEO와 동일하거나 오래된 오프셋을 나타낸다. 컨슈머는 High Watermark까지 기록된 메시지를 취득할 수 있다.(LEO에 기록되어 있지만 복제가 완료되지 않은 즉, High Watermark에 기록되지 않은 메시지를 취득한 경우, Leader Replica를 갖는 브로커가 복제를 완료하지 않는 타이밍에 고장이 발생하면 그 사위에 취득한 메시지는 두 번 다시 취득할 수 가 없는 상태가 된다.)

프로듀서의 메시지 도달 보증 수준

복제에 대한 중요한 구성 요소로 프로듀서의 메시지 송신 시 Ack 설정에 대해 설명한다. 브로커에서 프로듀서로 메시지가 송신된 것을 나타내는 Ack를 어느 타이밍에 송신할 것인지를 제어하는 것은 성능과 내장애성에 큰 영향을 준다.

Ack 설정설명
0프로듀서는 메시지 송신 시 Ack를 기다리지 않고 다음 메시지를 송신한다.
1Leader Replica에 메시지가 전달되면 Ack를 반환한다.
all모든 ISR의 수만큼 복제되면 Ack를 반환한다.

프로듀서는 타임아웃 설정으로 Ack가 돌아오지 않고 타임아웃 된 Send 처리를 송신 실패로 감지한다.
참고로 Ack를 1 또는 all롤 설정했을 경우 Ack 반환 타이밍이 의미하는 것은 각 복제에 '메시지가 전달'된 것으로 판단해 Ack를 반환하는 타이밍이다. 그리고 이 타이밍에는 메시지가 디스크에 flush되는 것이 아니라 메모리(os버퍼)에 기록된다.

In-Sync Replica와 Ack==all, 쓰기 계속성의 관계

ISRAck의 설정에 따라 프로듀서의 쓰기 동작의 예를 다음 두가지 패턴으로 설명한다.

브로커 4대, 레플리카 수 3, 브로커 1대가 고장나서 레플리카를 하나 잃어버린 경우

  • min.insync.replicas=3, Ack=all인 경우
    브로커 서버가 1대 고장난 경우 프로듀서는 비정상 상태로 간주하여 잃어버린 레플리카가 ISR로 복귀할 때까지 데이터를 쓸 수 없다.
  • min.insync.replicas=2, Ack=all인 경우
    브로커 서버가 1대 고장난 경우에도 Ack를 반환하고 처리를 계속한다. 처리를 계속하는 점에 있어서 위의 경우보다는 나은 반면, 나중에 추가된 파티션이 복제를 완료해 ISR로 승격될 때까지 복제 수가 2가 된다. 복구 전에 2대가 고장난 경우는 처리 중인 메시지를 손실할 위험이 높아진다.

min.insync.replicas 설정은 서버 고장 시 '데이터(메시지)를 잃지 않는 것'과 '메시징 시스템을 포함한 전체 시스템의 처리를 계속하는 것' 사이의 균형을 조정하는 설정 항목이다. 시스템 요구 사항과 제약 조건에 의해 결정돼야 한다는 점에 주의해야 한다.


정리

카프카의 특징과 장점

  • 스케일 아웃 구성
    - 메시지를 중계하는 브로커를 여러 대 구성할 수 있으며, 브로커 수를 증가함으로써 클러스터 전체의 처리량을 증가시킬 수 있다.
  • 데이터의 디스크 영속화
    - 브로커에서 수신한 메시지는 디스크에 기록되어 영속화된다. 디스크 용량에 다라 장기간의 과거 데이터를 저장, 재취득 가능하다.
  • 연계할 수 있는 제품 존재
    - 프로듀서/컨슈머를 구현하기 위한 API가 제공되어 이를 구현한 OSS가 많이 존재한다.
  • 메시지의 전달 보증
    - AckOffset Commit 방식으로 메시지가 제대로 송수신되었음을 확인하고 실패 시 재시도를 허용한다.
profile
백엔드

0개의 댓글