본문 바로가기
개발 지식/Kafka

[Kafka] 카프카는 어떻게 구성 되어 있는가 (feat. 디자인)

by 에르주 2022. 5. 24.
반응형

최근 국내외 많은 서비스들이 MSA(Micro Service Architecture)를 설계하면서 Kafka를 도입하고 있습니다. 

 

MSA에서의 동기성 데이터 처리는 API를, 대용량의 비동기 데이터 처리 시에는 Kafka를 활용하고 있습니다.

또한 Kafka는 Producer와 Consumer 단순히 데이터 파이프 라인 흐름 뿐만 아니라 ksql, Kafka Streams 그리고 하둡등 3rd Party 빅데이터 플랫폼 연동을 통해 그 확장성이 커지고 있습니다.

 

1) Kafka의 도입 배경

Kafka는 2011년 LinkedIn에서 처음 출발... (생략) ...

Kafka가 도입 배경은 크게 두가지 이유가 있습니다.

 

  • 실시간 트랜잭션 처리와 비동기 처리가 동시에 이루어지지만 통합된 전송 영역이 없었다. → 데이터 전송은 알아서 어디서 누군가가 맡아서 하겠지..
  • 데이터 파이프관리의 어려움 → 이 데이터는 어디서부터 흘러나온거야..?

 

이를 해결하고자 했던 것들은 4가지 목표였습니다.

  • 프로듀서(Producer)와 컨슈머(Consumer)의 분리 → 알아서 주고 받기.
  • 메시징 시스템과 같이 영구 메시지 데이터를 여러 컨슈머 (Consumer)에게 허용 → 재방송 하기 싫어. 단톡방처럼 여러 사람들이 받아 볼 수 있도록
  • 높은 처리량을 위한 메시지 최적화 → 데이터는 빠르게 그리고 최대한 성능 좋게
  • 데이터가 증가함에 따라 스케일 아웃이 가능한 시스템 → 데이터 처리에 부족함이 없게

 

2) Kafka의 기초 모델 및 동작원리

 

 

동작 원리

Pub/Sub 모델 → ex. 유튜브 구독 시스템 (구독 및 알람설정)

Producer (메시지 발행자, 메시지 보내는 자) → Kafka → Consumer (구독하는 자)

(여기서 Producer와 Consumer는 각자 알아서 잘 보내고 잘 받으면 된다.)

 

3) 특징

 

3-1) 알아서 잘 보내고 받는다 → 시스템이 각자 독립적이다 → 한쪽 장애포인트 발생시 연쇄 작용으로 문제가 발생할 확률은 낮다. 

또한 스케일업 또는 추가 아키텍처 구성시에도 카프라로 데이터만 흐르면 되기 때문에 리스크가 적다. 

 

3-2) 멀티 프로듀서, 멀티 컨슈머 재방송 하기 싫어, 단톡방처럼 여러 사람들이 받아 볼 수 있도록 할래 (슬랙이나 카톡을 사용하게 되다보면 같은 채널 또는 같은 카톡방 안에 있는 사람들 모두  해당 메시지를 확인 할 수 있다.)

 

3-3) 디스크에 메시지 저장

영구 메시지 데이터 → 보관 주기 동안 디스크에 메시지 저장, 컨슈머 처리가 늦더라도 Kafka 디스크에 안전하게 보관되기 때문에 메시지 손실 방지

 

3-4) 확장성

Kafka 클러스터는 3대의 브로커(Kafka)로 시작해 수십대 브로커로 확장가능, 일반적인 복제 factor는 3 이상, 즉 항상 3개 이상의 데이터 복사본이 있습니다.

 

3-5) 높은 성능

하루에 1페타 바이트 이상의 데이터 처리

 

 

조금 더 자세히 카프카 내부 클러스터를 들여다 봅시다.

 

  •  

1) 메시지 보내는 사람 (Producer)

2) 메시지를 중간에 관리하는 시스템 (Kafka)

3) 메시지 받는 사람 (Consumer)

4) 메시지 토픽: 메시지를 받을 수 있는 논리적 묶음 단위 (ex. 유튜브 채널), 프로듀서는 토픽 단위로 메시지 발행, 컨슈머는 토픽 단위로 구독 

5) Kafka 브로커 (== Kafka)

6) 파티션 : 토픽을 구성하는 데이터 저장소로 수평 확장이 가능한 단위

 

파티션이 필요한 이유 

ex) TVING 예능 토픽으로 하나의 프로듀서에서 4개의 메시지(A, B, C, D) 를 전송해야 합니다. 단 Kafka로 메시지 보내는데 걸리는 시간은 1초입니다.

1) 프로듀서 1개, 파티션 1개 일 경우 4개의 메시지를 모두 전송하는데 걸리는 시간은 몇초 일까요? → 4초

2) 프로듀서가 4(a, b, c, d)개, 파티션 1개라 해도 메시징 큐 시스템의 경우에는 순서가 보장되어야 하므로 a-message, b-message, c-message, d-message등 일렬로 처리해야 하므로 → 그대로 4초

3) 프로듀서가 4(a, b, c, d)개, 파티션-1 ,2, 3, 4 로 늘리면 병렬 처리 방식으로 동시에 하나의 토픽 파티션으로 보낼 수 있게 된다 → 1초

 

파티션 예시)

메시지 데이터: a, b, c, d, e, 1, 2, 3, 4, 5

파티션 0 : b,e,2,5

파티션 1: a,d,1,4

파티션 2: c,3

출력 a, d, 1, 4, b, e, 2, 5, c, 3 (파티션 1 // 파티션 0 //  파티션2)

 

But, 파티션이 무조건 적으로 늘려야 하나

No.

1) 파일 리소스 및 핸들러의 낭비

  • 저장되는 데이터마다 2개의 파일 (인덱스, 실제 데이터) 생성, 파일 수가 많아져 리소스 낭비

2) 장애 복구 시간 증가

높은 가용성을 위해 Kafka는 리플리케이션(복제)을 지원 합니다.

  • Kafka 클러스터 브로커 중 하나만 컨트롤러가 존재한다. 컨트롤러 브로커  : 그외 브로커  =  1 : N
  • 브로커는 여러개의 파티션이 존재 : 브로커 : 파티션 = 1 : N
  • 파티션은 리더와 팔로워로 나뉜다, 리더 : 팔로워 = 1 : N

 

ex) 하나의 브로커에 1000개 파티션이 있다. 갑자기 브로커가 갑자기 종료되면 일시적으로 1000개 사용 불가, 파티션의 리더를 다른 브로커가 있는 곳으로 이동시켜야 사용할 수 있습니다.

컨트롤러가 각 파티션 별로 새로운 리더를 선출하는데 5ms 걸린다 하면 1000개 일 경우 5초 장애 발생

진짜 심각하게! 컨트롤러 브로커가 장애시에는 새 컨트롤러가 초기화하는 동안 주키퍼에서 모든 파티션의 데이터를 읽어야 하는데 파티션당 2ms라는 적은 시간이 걸린다 해도 많은 파티션이 있다면 그 만큼 오랜 시간 동안 장애 상황이 발생 할 수 있습니다.

카프카 파티션

(https://kafka.apache.org/documentation/#gettingStarted)

 

파티션에 대한 자세한 설명은

https://developer.confluent.io/learn-kafka/apache-kafka/partitions/?_ga=2.153975864.1010619977.1637764032-1352589646.1637764032&_gac=1.181521109.1637764040.CjwKCAiA4veMBhAMEiwAU4XRr0um66kOtxlcYxQoe1ABvvUbDrRnvoG5tMIOyneSPfryW7LTywC8tBoC9o0QAvD_BwE

 

휴.. 간단히 명칭에 대해서 살펴 봤으니 이번에 메인 주제인 카프카 내부 도메인 그리고 내부 디자인 형태를 좀 들여다 보도록 하겠습니다.

 


카프카 디자인

 

1) Motivation

Kafka는 모든 실시간 데이터 피드를 처리하기 위한 통합 플랫폼 역할을 할 수 있도록 설계했습니다.

즉 높은 처리량을 가지고 있어야 했고 오프라인 시스템에서 주기적으로 데이터를 로드할 수 있도록 빅 데이터 백 로그를 정상적으로 처리 해야 했습니다.

 

2) Persistent

 

디스크에 메시지 저장

  • 영구 메시지 데이터 → 보관 주기 동안 디스크에 메시지 저장, 컨슈머 처리가 늦더라도 Kafka 디스크에 안전하게 보관되기 때문에 메시지 손실 방지

 

Kafka는 메시지를 저장하고 캐싱 즉 데이터 값들을 파일 시스템에 의존합니다. 디스크에서 파일 불러오는 것은 느리다 라는 인식이 있다는 생각을 많이 가지고 있습니다.

사실 디스크는  사람들이 기대하는 것보다  훨씬 느리고 훨씬 빠를 수도 있습니다. 적절하게 설계된 디스크 구조라면 네트워크 만큼 빠를 수도 있습니다.

 

어떻게 그럴수가...? 

디스크 성능에서 가장 중요한 사실은 하드 드라이브의 처리량이 지난 10년 동안 디스크 탐색의 대기 시간에서 벗어나고 있었다는 것입니다.

JBOD방식의 7200rpm SATA RAID-5 Array 600MB/sec이지만 임의 쓰기는 100k/sec로 거의 6000배 차이납니다.

이러한 선형 읽기 쓰기가 대부분이며 모든 사용 패턴을 예측하고 운영 체제에 의해 최적화 됩니다. 현재 대부분의 운영체제는 블록 베이스의 데이터를 사전 추출하고 미리 읽고 및 쓰기를 할 수 있습니다.

미리 읽기 및 쓰기 기술이라고 하는 것은 디스크 데이터를 큰 블록 배수로 먼저 Fetch하고 작은 논리적 쓰기를 큰 물리적 쓰기로 그룹화 한다는 것입니다.

 

아래 표를 보시면 순차적 디스크 엑세스가 임의 메모리 엑세스보다 빠를 수 있습니다.

디스크 속도

 

이러한 차이를 극복하기 위해  운영 체제는 디스크 캐시(하드 디스크와 같이 데이터 보관 수정을 위해 사용되는 RAM의 영역)를 위해 주 메모리(RAM)를 사용합니다. 또한 최신 OS는 메모리를 회수 할 때 성능 저하 없이 모든 여유 메모리를 디스크 캐시로 전환 합니다.

잔여 메모리를 활용하게 되면 디스크에 읽고 쓰기를 하지 않고 페이지 캐시를 통해 읽고 쓰므로 처리 속도가 매우 빠르고 전체적인 성능 향상을 시킬 수 있습니다.

모든 하드 디스크 읽기 및 쓰기는 통합 캐시(프로세스 내 캐시 데이터, 메모리 내 페이지 캐시)를 거칩니다. 프로세스가 데이터의 프로세스 내 캐시를 유지하더라도 데이터는 OS 페이지 캐시에 복제되어 모든 것을 효과적으로 두번 저장합니다.

 

 

카프카 디스크 구성

 

즉. 파일 시스템을 사용하고 페이지 캐시를 사용합니다.

 

3) 효율성

 

주요 사용 사례 중 하나 웹 활동 데이터 처리 →  큰 데이터 볼륨, 수십 개의 쓰기 생성 이벤트 발생

 

Kafka는 인프라보다 먼저 부하가 걸릴 수 있도록 보장하고 있습니다. 인프라가 부하 걸려 다운이 되면,,? 지옥불

불량한 디스크 액세스 패턴(단순 파일 읽기)이 제거되면 Kafka에서는 두가지 일반적인 비효율성의 원인이 있다고 진단합니다.

 

  • 너무 많은 I/O 작업

 

클라이언트와 서버 간에 그리고 서버 자체의 처리에서 모두 발생합니다.

예를 들어 서버와 클라이언트 통신 사이에서 매우 작은 메시지를 한번에 하나씩 그리고 보내는 시간이 1초라고 하면 작은 메시지 보내는 데 총 4초가 소요됩니다.

But. 그룹화 하여 데이터 전송은 단일 메시지 데이터를 주고 받는 것보다 네트워크 오버헤드를 방지할 수 있습니다. → 메시지 4개를 한꺼번에 보내면 1초가 소요 됩니다.

메시지를 그룹화 하는 메시지 그룹 추상화 구축, 일괄 처리 네트워크 더 큰 패킷, 더 큰 순차 디스크, 연속 메모리 블록등 버스트 스트림을 컨슈머에게 흐르는 선형 쓰기로 전환 할 수 있다.

 

  • 과도한 바이트 복사

 

메시지 로그 자체는 프로듀서와 컨슈머가 사용하는 것과 동일한 형식으로 메시지 세트가 채워진 파일 디렉토리입니다. 부하가 걸리면 영향이 상당하기 때문에 프로듀서, 브로커 및 컨슈머가 공유하는 표준화된 이진 메시지 형식을 사용합니다. (ex. 누구는 Json 쓴다더라 누구는 xml 쓴다더라 →  메시지가 다르다 → 파싱 하는 로직 필요 → 파싱 된 데이터를 읽는 로직 필요 → ...... never Ending)

공통 형식 유지는 영구 로그의 네트워크 전송을 최적화 할 수 있습니다.

 

종단 간 일괄 압축

 

병목 현상은 CPU나 디스크가 아니라 네트워크 대역폭에서 발생 할 수 있습니다. Kakfa는 효율적인 일괄 처리 형식으로 이를 지원,메시지를 일괄 압축하여 서버로 보낸다. 압축 형식으로 작성 로그에 압축된 상태로 츄지 컨슈머만 압출을 풀 수 있다.

 GZIP, Snappy, LZ4 및 ZStandard 압축 프로토콜을 지원한다. 

 

압축에 대한 자세한 알고리즘과 내용은

https://cwiki.apache.org/confluence/display/Kafka/Compression

 

 

4) 프로듀서

파티션의 리더인 브로커에게 직접 데이터를 보냅니다. 프로듀서가 수행 할 수 있도록 모든 Kafka 노드는 어떤 서버가 활성 상태이고 주제 파티션의 리더가 어디 있는지에 대한 메타 데이터에 요청하여 프로듀서가 요청을 적절하게 지시할 수 있도록 한다.

메모리에 데이터를 축적하고 단일 요청으로 더 큰 일괄 처리를 보내려고 시도한다. 고정된 대기 시간 제한 보다 오래 기다리지 않도록 구성할 수 있다. 처리량 향상을 위해 약간의 추가 대기 시간을 절충하는 메커니즘을 제공합니다.

 

5) 컨슈머

브로커에 페치 요청을 발행하여 작성 즉 Kafka → 컨슈머 Push 형태가 아닌 컨슈머에서 Fetch 요청을 먼저 진행합니다.

푸시 기반은 브로커가 데이터 전송 속도를 제어하기 때문에 다양한 컨슈머를 다루는데 어려움이 있습니다.  컨슈머 데이터 처리 속도가 생산 속도 아래로 떨어질 때 장애 발생이 높습니다. (먹는 속도보다 소화되는 속도가 느리면 배부르다.)

 

Pull 즉 Fetch 기반 시스템은 컨슈머가 단순히 뒤쳐져 있을 수 있을 때 즉 데이터를 빠르게 처리 못하고 있을 경우 컨슈머의 처리량 또는 config을 통해 극복할 수 있습니다.

데이터가 없을 때에도 Pull 하는 경우가 있어 대기 하는 긴 폴에서 차단할 수 있도록 매개변수 및 config 설정을 해야 합니다.

 

대부분의 메시징 시스템에서는 브로커에서 사용된 메시지에 대한 메타 데이터를 유지합니다. 즉 메시지 데이터가 컨슈머에게 전달되면 브로커는 해당 사실을 즉시 기록하거나 컨슈머의 승인을 기다릴 수 있습니다.

 

1) 브로커가 메시지가 네트워크를 통해 전달 될 때마다 즉시 소비 된 경우 → 컨슈머 메시지 처리 불가 → 메시지 손실

2) 브로커는 메시지를 소비 된것으로 기록하기 위해 컨슈머의 특정 승인을 기다린다. → 컨슈머가 메시지를 처리하지만 승인을 보내기 전에 실패하면 다시.. → 성능 문제

 

Kafka는 완전히 정렬된 파티션 세트로 나뉘며 각 파티션은 주어진 시간에 각 구독 컨슈머 그룹 내에서 정확히 한 컨슈머가 소비합니다. 각 파티션에서 컨슈머의 위치가 소비할 다음 메시지 오프셋인 단일 정수. 소비 된 것에 상태를 각 파티션에 대한 하나의 숫자를 부여합니다.

 

git history에 나오는 git commit hash 값을 이용하여 revert, reset 하는 것처럼 데이터를 다시 사용할 수 있습니다.

 

카프카 파티션 및 오프셋

 

6) 메시지 전달 

At most Once - 메시지 손실될 수 있지만 다시 전달 하지 않는다.

At least Once - 메시지 손실되지 않더라도 다시 전달 할 수 있다.

Exactly Once -  메시지는 한번만 전달됩니다. (We want it!)

 

프로듀서 관점에서의 메시지 전달

메시지를 게시할 때 메시지가 로그에 커밋 된다는 개념이 있습니다. (git commit 하듯! ) 게시된 메시지가 commit 되면 이 메시지가 기록되는 파티션을 복제하는 하나의 브로커가 활성 상태를 유지하는 한 손실 되지 않습니다.

 

Kafka 버전 0.11.0.0(Release 날짜 2017/06/28, 2020/5/23 기준 최신버전 3.2.0) 이전에는 프로듀서가 메시지 커밋 응답을 받지 못하면 메시지를 다시 보냈습니다. 즉 'At most Once'가 적용 되었습니다.

하지만 그 후 버전부터는 프로듀서가 재전송으로 인한 중복 항목이 발생하지 않도록 보장하는 옵션이 추가 되었습니다.

 

Kafka는 각 프로듀서에게 ID를 할당하고 모든 메시지와 함께 프로듀서가 보낸 시퀀스 번호를 사용하여 메시지 중복을 제거합니다. 이렇게 Kafka는 우리가 원하는 'Exactly Once'을 이렇게 정의하여 구성하였습니다.

물론 지연 시간에 민감한 시스템인 경우 프로듀서가 원하는 내구성 수준을 설정할 수있으며 커밋되는 메시지를 저장 및 쓰기에 소요되는 시간을 10ms 정도 설정할 수 있습니다. 그리고 리더가 메시지를 받을 때까지만 기다리도록 지정할 수도 있습니다.

 

 

컨슈머 관점에서의 메시지 전달

모든 복제본에는 Offset이 정확히 동일한 데이터가 있습니다. 컨슈머는 이 데이터에서 자신이 읽은 위치를 제어합니다.

컨슈머가 메시지를 처리하고 위치 즉 Offset을 업데이트 하기 위한 몇 가지 옵션이 있습니다.

 

1) Read → Save → Function : 메시지를 읽은 다음 로그 위치를 저장하고 마지막으로 메시지를 처리

컨슈머 프로세스에서 위치를 저장한 후 메시지 처리 출력을 저장하기 전에 충돌할 가능성이 있습니다.

처리를 인계받은 프로세스는 해당 위치 이전의 몇가지 메시지가 처리 되지 않은 경우에도 저장된 위치에서 시작됩니다. 이는 컨슈머 실패 메시지가 처리되지 않을 수 있는 경우 → 'At most Once'

 

2) Read → Function → Save  : 메시지를 읽고 처리하고 위치를 저장.

컨슈머 프로세스가 메시지를 처리한 후 위치를 저장하기 전에 충돌할 가능성이 있습니다. 새 프로세스가 받은 처음 몇개의 메시지는 이미 처리 된 것 입니다. 컨슈머 실패의 경우 'At least Once' 해당

 

 

컨슈머의 위치는 토픽에 메시지로 저장되므로 처리된 데이터를 수신하는 출력 주제와 동일한 트랜잭션에서 Kafka에 오프셋을 쓸 수 있습니다 (0.11.0 버전부터)

https://issues.apache.org/jira/browse/KAFKA-5059

 

 

7) 복제

Kafka 클러스터의 서버가 실패할 경우를 대비하여 파티션에 대한 로그를 복제합니다. 자동으로 failover가 적용됩니다. 이는 Kafka 내 설정값을 통해서 변경 할 수 있습니다. (server.properties). 기본 값은 1입니

다.  모든 브로커에 동일하게 적용 되며 변경 한 후 브로커 1대씩 재시작을 하면 변경 내용이 적용됩니다

 

복제 단위는 토픽 파티션 입니다. Kafka에서는 단일 리더와 0개 이상의 팔로워가 있습니다. 1:N 관계입니다.

모든 토픽에 대한 쓰기는 파티션의 리더로 이동하고 읽기는 파티션의 리더 또는 팔로워로 이동할 수 있습니다. 일반적으로 브로커보다 많은 파티션이 있으며 리더는 브로커 간에 고르게 분포되어 있습니다.

팔로워의 로그는 리더의 로그와 동일하며 모두 동일한 오프셋과 동일한 순서로 메시지를 가집니다.

 

리더와 로그의 팔로워 또한 다음과 명령어를 통해서 확인 할 수 있습니다. (해당 예시는 replica 값이 1)

 

해당 파티션 노드(리더/팔로워)에 대한  살아 있다는 것은

  1. 노드는 주키퍼와의 세션을 유지할 수 있어야 합니다. (하트비트 매커니즘)
  2. 팔로어인 경우 리더에서 발생하는 쓰기를 복제해야 하며 "너무" 뒤져지지 않아야 합니다

 

두가지를 모두 만족하는 노드가 동기화된 토픽 파티션의 리더는 동기화 토픽 파티션 세트(팔로워값들)를 추적합니다. 팔로워가 죽거나 갇히거나 뒤처 지면 동기화된 복제본 목록에서 팔로워에서 제거 합니다.

중단된 복제본과 지연된 복제본의 결정은 replica.lag.time.max.ms 값 구성에 의해 제어됩니다.

 

해당 파티션의 모든 동기화 복제본이 토픽에 대한 발생된 메시지를 로그에 적용했을 때 메시지가 커밋된 것으로 간주. 커밋된 메시지만 컨슈머에게 제공됩니다. 프로듀서는 대기 시간과 내구성 간의 균형에 대한 선호도에 따라 메시지가 커밋 될 때까지 기다릴지 여부를 선택할 수 있습니다. 이 설정은 ack 설정에 의해 제어됩니다. ack가 의미 하는 것은 동기화 복제본의 '최소 수'에 대한 설정입니다.

  • ack 옵션
    • ack=0 인 경우
      • 프로듀서는 리더 파티션에 데이터를 전송하고, 응답값을 받지 않는다.
      • 브로커로 부터 응답을요청하지 않아 브로커 내 상태 알지 못하고 예외 발생시 데이터 손실 가능성 있음
      • 속도는 빠르다.
    • ack=1 인 경우 (default)
      • 프로듀서는 리더 파티션에 데이터를 전송하고 응답값을 받는다.
      • 나머지 파티션에 정상적으로 복제는 보장되지 않는다.
      • 승인이 수신 되지 않으면 프로듀서는 중복 데이터 없이 재시도 될 수 있다.
      • 리더가 오프라인 상태, 복제본이 아직 데이터를 복제하지 않았을 경우는 데이터 손실 될 수 있다.
    • ack=all 인 경우
      • 리더 파티션이 데이터를 잘 받았는지 응답값을 받고 팔로워 파티션에도 잘 복제가 되었는지 응답값을 받는다.
      • 데이터 유실 가능성은 없지만 속도가 느리다.

 

다만 리플리케이션 팩터 값을 무분별하게 증가 시키는 것은 토픽 파티션에 해당하는 사이즈 값이 똑같이 복제되는 것이므로 Kafka 클러스 내 필요 저장소 크기는 증가하게 됩니다.

 

 

8) ISR

위의 사진을 보면 Isr이라고 표시된 부분이 있을 것입니다.

ISR이라는 것을 설명하기 전에 Kafka는 리더와 팔로워가 각자 역할을 맡아 리플리케이션 작업을 처리한다는 것을 다시 한번 생각해봅시다.

 

리더와 팔로워 모두 주어진 역할에 맞게 잘 동작하고 있으면 전혀 문제 없지만 팔로워에 문제가 있어 리더로부터 데이터를 fetch 하지 못하는 경우 즉 정합성이 맞지 않게 된다면 문제가 발생합니다.

리더가 다운되는 경우 팔로워가 새로운 리더로 승격되어야 하는데 데이터가 일치 하지 않으므로 데이터 손실이 발생 할 수 있습니다.

 

Kafka는 이러한 현상을 방지하고 자 ISR(In Sync Replica) 이라는 개념을 도입했습니다. ISR이라는 것은 리플리케이션 그룹입니다. 그리고 Kafka ISR 리플리케이션 구성원들만 리더의 자격을 가질 수 있도록 을 유지 관리합니다. 

Kafka 파티션에 대한 쓰기는 모든 동기화 된 복제본이 쓰기를 수신 할때까지 커밋된 것으로 간주되지 않습니다. 또한 ISR 세트는 변경될 때마다 주키퍼에 유지됩니다.

  • 리더의 자격을 가질 수 있다 → 리더와의 데이터 동기화 작업을 매우 중요하게 처리하는 팔로워이다. → 즉 리플리케이션의 신뢰성을 높인다.

 

 

모든 브로커가 다운된다면 대단히 심각 한 사항이다. (비상이다 비상)

1) Kafka 클러스터는 3대의 브로커로 구성되어 있다

2) 토픽의 복제 옵션은 3

3) 프로듀서가 데이터를 보내는 중 브로커가 1대씩 다운

4) 모든 브로커 다운!

 

 

a) 프로듀서가 A 메시지를 전송했고 리더와 팔로워들은 모두 A 메시지 저장

b) 프로듀서가 B 메시지를 전송하기 직전에 팔로워2가 있는 브로커가 다운되었고 리더는 팔로워2에서 ISR에서 제외한다. 프로듀서는 B 메시지를 전송하고 리더와 팔로워1은 메시지를 저장한다.

c) 프로듀서가 c메시지를 전송하기 직전에 갑작스럽게 팔로워1이 있는 브로커가 다운되었고 리더는 팔로워1을 ISR에서 제외

d) 프로듀서가 d메시지 전송 리더 프로커 다운, 리더가 존재 하지 않습니다.

 

이럴 경우 구현할 수 있는 두가지 동작이 있습니다.

  1. ISR의 복제본이 다시 활성화될 때까지 기다렸다가 이 복제본을 리더로 선택합니다(모든 데이터가 있기를 바랍니다).
  2. 리더로 다시 살아나는 첫 번째 복제본(ISR에 있을 필요는 없음)을 선택합니다.

 

이것은 가용성과 일관성 사이의 절충점 입니다.

1번 과 같은 경우 모두 활성화하면 메시지 데이터 값들은 모두 정상적으로 저장되어 있기 때문에 서비스를 지속적으로 발생 할 수 있다. But 재시작이 마지막 리더가 반드시 시작되어야 합니다.

2번과 같은 경우  ISR에서 추방되었지만 먼저 살아나면 자동으로 리더가 되는 경우에는 마지막 리더가 아닌 새로운 리더가 됩니다. 이는 메시지 손실이 발생합니다.

 

기본적으로 버전 0.11.0.0이하는 2번째 전략을 선택하고 그 이상 버전에서는 Kafka는 첫 번째 전략을 선택하고 일관된 복제본을 기다리는 것을 선호합니다.  하지만만 Kafka 설정 파일에서 원하는 옵션으로 설정할 수 있습니다.

 동작은 구성 속성 unclean.leader.election.enable을 사용하여 변경하여 일관성보다 가동 시간을 선호하는 사용 사례를 지원할 수 있습니다. true: 2번 방안, false: 1번 방안

 

 

참고 문헌)

1) https://kafka.apache.org/documentation/

2) 카프카 데이터 플랫폼의 최강자 서적

 

 

반응형

댓글