본문 바로가기

Kafka

Kafka 신뢰성 보장

이번 글에서는 카프카에서 보장할 수있는 신뢰성은 어떤것인지, 신뢰성을 보장하기 위해 브로커, 프로듀서, 컨슈머를 각각 어떤식으로 구성하면 될 것인지를 알아볼 예정이다.

 

카프카에서의 신뢰성

아파치 카프카에서 보장하는 것들은 무엇인지 아래의 항목들을 살펴보자

- 카프카는 파티션의 메세지 순서를 보장한다

- 각 파티션의 모든 동기화 리플리카에 메세지를 썼다면, 해당 메세지는 '커밋' 된 것으로 간주한다

- 최소한 하나의 리플리카가 살아있다면, 커민된 메세지는 유실되지 않는다

- 컨슈머는 커밋된 메세지만 읽을 수 있다

 

복제

복제 메커니즘은 카프카의 신뢰성 보장의 핵심이다. 

 

복제된 리플리카들의 동기화 여부 체크

- 주키퍼와 세션이 연결되어 있는 경우 (주키퍼와 리플리카 간의 하트비트 전송 시간이 존재함 default 6초)

- 최근 10초(기본값) 내에 리더로부터 메세지를 읽은 경우

- 최근 10초(기본값) 내에 리더로부터 가장 최근 메세지를 읽은 경우(리더와 리플리카 간의 지연이 존재하면 안됨)

 

위 항목들 중 하나라도 해당하는 경우 비동기화 상태로 간주하며, 이 경우 동기화 리플리카의 갯수를 어느정도 구성 해 놓았는지, 프로듀서 전송 방법(ack)을 어떤식으로 설정했는지에 따라, 프로듀서와 컨슈머의 처리속도에 대항 성능이 저하 될 수 있다.

 

신뢰성있는 브로커 구성하기

신뢰성과 관련된 브로커 설정 매개변수는 세 가지가 있다. 본인의 운영사항에 맞춰 각 매개변수들에 대한 설정이 필요하다.

 

replication.factor

토픽 수준에서 리플리카의 갯수 설정을 위한 매개변수로써, 가용성과 하드웨어 간의 트레이드오프가 존재한다. 그러므로 토픽의 중요도와 높은 가용성에 따른 지불 가능 비용을 고려하여 결정해야 한다.

 

replication.factor = N인 경우,

- N-1개의 브로커가 중단되더라도 여전히 메세지를 신뢰성있게 읽거나 쓸 수 있어서 가용성과 신뢰성이 높아지고 장애에 따른 데이터 유실은 적어진다.

- 반면, 최소한 N개의 브로커가 필요하고, N개의 복사본을 저장해야 하므로 N배의 디스크 공간이 필요하다

 

unclean.leader.election.enable(defulat=true)

리더 리플리카가 중단된 경우, 그런데 나머지 팔로어 리플리카들이 메세지 동기화가 모두 안되어 있는경우(동기화 지연 이슈로 인한 혹은 동기화 하고 있는 찰나의 순간에 중단된 경우), 데이터 유실을 감안하고 동기화 되지 않은 리플리카를 선출(unclean leader) 할 것인지에 대한 설정 값이다.

 

- true의 경우, 데이터 품질과 일관성보다 가용성이 더 중요한 경우 사용(예를들어, 실시간 클릭 정보 분석)

- false의 경우, 원래 리더가 온라인이 되기를 기다린다는 의미로 가용성이 떨어지지만, 데이터 품질과 일관성을 보장할 수 있다

 

min.insync.replicas

최소한으로 동기화 할 리플리카의 개수를 설정하는 매개변수로써, 이 매개변수에 설정된 N개의 리플리카에 메세지가 모두 동기화 된 경우에만 정상 처리로 간주하게 된다.

 

혹, N개 모두 동기화 되지 않은 상태에서 처리를 요청 하거나 N개 중에서 몇 대가 중단되는 경우 브로커들은 더 이상 쓰기 요청을 받지 않으며, 프로듀서의 쓰기요청에 대해서는 NotEnoughReplicasException 예외를 받게 된다. 이를 복구 하려면 설정한 N개의 리플리카를 정상화 하여 그동안 밀렸던 메세지를 처리하고 동기화 하도록 해야 한다.

 

컨슈머는 위의 경우와 상관 없이 브로커의 메세지들을 계속 읽을 수 있다. 

 

신뢰성있는 프로듀서 구성하기

신뢰성 있는 프로듀서를 구성하기 위해서는 아래 두 가지에 대해 고민하자

- 신뢰성 요구 사항에 맞도록 acks 구성 매개변수를 올바르게 설정하기

- 구성 매개변수와 코드 모두에서 에러 처리를 올바르게 하기

 

프로듀서에서의 에러 처리에는 프로듀서가 자동으로 처리하는 에러와 개발자가 직접 처리해야 하는 에러 두가지가 존재한다.

 

자동으로 처리 가능한 에러

재시도 가능한(retries) 에러를 처리 할 수 있다.

예를들어 LEADER_NOT_AVAILABLE 에러 코드를 반환하면, 프로듀서는 메세지 전송을 다시 시도하면 된다.

 

개발자가 처리해야 하는 에러

- 메세지 크기, 인증 에러 등과 같이 재시도 불가능한 브로커 에러

- 메시지가 브로커에게 전송되기 전에 발생한 에러. 예를들면 직렬화 에러

- 프로듀서 메모리가 꽉 찼을때 발생하는 에러

 

신뢰성있는 컨슈머 구성하기

컨슈머 입장에서 신뢰성을 보장한다는 의미는, 읽은 메시지와 읽지 않은 메시지를 계속 파악하는것을 의미한다.

이는 컨슈머 중 한 대가 중단되더라도 어디서부터 읽어야 할지 다른 컨슈머가 알아야 메세지 중복 없이 메시지를 읽을 수 있기 때문이다.

이는 컨슈머가 자신의 오프셋을 '커밋'해야 하는 이유 이기도 하다.

 

신뢰성을 보장하기 위한 속성들을 살펴보자

group.id

동일한 그룹 ID를 갖는 컨슈머들은 해당 토픽의 일부 파티션을 분담해 각자 할당받은 파티션의 메세지를 읽도록 구성 된다. 

 

auto.offset.reset

커밋된 오프셋이 없을 때(컨슈머가 최초로 시작될 때), 또는 브로커에 없는 오프셋을 컨슈머가 요청할 때 컨슈머가 할 일을 이 매개변수를 통해 설정이 가능하다

- earliest : 해당 파티션의 맨 앞부터 모든 데이터를 읽음(중복 메세지 읽기 가능성 존재함)

- latest : 파티션의 제일 끝부터 읽기 시작함(메세지 유실 가능성 존재함)

 

enable.auto.commit

컨슈머의 오프셋 커밋을 자동으로 할 것인지를 설정하는 매개변수이다.(default true)

 

auto.commit.interval.ms

enable.auto.commit 설정값이 true인 경우 자동으로 오프셋을 커밋하는 시간 간격을 설정하는 매개변수 이다.(defulat 5s)

오프셋 자동 커밋을 자주 할 수록 컨슈머의 중단으로 인해 초래될 수 있는 중복 메세지의 수를 줄일 수 있지만 약간의 부담이 따른다.

 

 

시스템 신뢰성 검사하기

구성검사, 애플리케이션 검사, 모니터링을 통해 시스템의 신뢰성을 검사하는것을 권장한다

 

구성검사

아파치 카프가에서 구성 검사를 위해 제공하는 도구들이 org.apache.kafka.tools 패키지에 존재한다

- VerifiableProducer : acks, retries 설정 후 임의 데이터를 카프카에 쓴 후 성공 또는 에러 출력

- VerifiableConsumer : VerifiableProducer가 쓴 메시지를 읽은 후 순서대로 출력하며 커밋과 리밸런싱에 관련된 정보도 출력

 

애플리케이션 검사

각자 개발하는 애플리케이션에서 에러 처리 코드, 오프셋 커밋, 리밸런싱 리스너, 그리고 카프카의 클라이언트 라이브러리와 상호 작용하는 애플리케이션 로직 등을 확인한다

 

모니터링

카프카의 자바 클라이언트는 JMX 메트릭을 포함한다.

- 프로듀서 : 레코드 당 에러율(error-rate), 재시도율(retry-rate)이 올라가진 않는지 모니터링 해야함. 이 외에 에러 로그(WARN레벨 포함)도 모니터링이 필요함

- 컨슈머 : 처리지연(lag) 메트릭 정보가 가장 중요함. 현재 컨슈머가 어느정도 뒤쳐지고 있는지 판단하는 기준