[카프카 핵심 가이드] Chapter 07. 신뢰성 있는 데이터 전달

Falco·2023년 12월 3일
0
post-thumbnail

7.1 신뢰성 보장

아마도 가장 잘 알려진 신뢰성 보장은 관계형 데이터베이스에서 대표적으로 지원하는 ACID입니다. 이는 원자성, 일관성, 격리성 ,지속성을 의미하며 어떤 데이터베이스가 ACID를 준수한다고 하면, 이는 틀랜잭션 처리 관련하여 어떤 행동을 보장함을 의미합니다.

카프카는 어떻게 신뢰성을 보장할까요?

  • 카프카는 파티션 안의 메시지들 간의 순서를 보장합니다. 만약 메시지 A 다음에 메시지 B가 쓰여졌다면, 동일한 프로듀서가 동일한 파티션에 썼을 경우, 카프카는 B의 오프셋이 A보다 큰 것을 보장합니다.

  • 클라이언트가 쓴 메시지는 모든 인-싱크 레플리카의 파티션에 쓰여진 뒤에야 '커밋'된 것으로 간주됩니다.

  • 커밋된 메시지들은 최소 1개의 작동 가능한 레플리카가 남아 있는 한 유실되지 않습니다.

  • 컨슈머는 커밋된 메시지만 읽을 수 있습니다.

카프카는 이러한 신뢰성을 보장함과 함께 설정 매게변수를 조절함으로써 어느정도 신뢰성을 조절할 수 있도록 개발되었습니다.

가용성, 높은 처리량, 낮은 지연, 하드웨어 비용, 신뢰성 등 다양한 고려사항에 맞추어 카프카를 활용해야합니다.

7.2 복제

카프카의 복제 메커니즘은 파티션별로 다수의 레플리카를 유지한다는 특성과 함꼐 카프카 신뢰보장의 핵심입니다. 하나의 메시지를 여러개의 레플리카에 씀으로써 카프카는 크래시가나더라도 메시지의 지속성을 유지합니다.

각 토픽은 파티션으로 이루어지며, 각 파티션은 하나의 디스크에 저장됩니다. 각 카프카는 파티션에 저장된 이벤트들의 순서를 보장하며, 각 파티션은 또 다수의 레플리카를 가질 수 있습니다. 모든 이벤트들은 리더 레플리카에 의해 쓰여지며, 읽혀집니다. 다른 레플리카들은 단순히 리더와 동기화를 맞추면서 최신 이벤트를 제 시간에 복사합니다.

레플리카는 파티션의 리더 레플리카이거나 아니면 아래의 조건을 만족하는 팔로워 레플리카인 경우 인-싱크 상태인것으로 간주합니다.

  • 주키퍼와의 활성 세션이 있다.(하트비트 교환)
  • 최근 10초 사이에 리더로부터 메시지를 읽어 왔다.
  • 최근 10초 사이에 리더로부터 읽어 온 메시지들이 가장 최근 메시지이다.

7.3 브로커 설정

신뢰성과 관련된 브로커의 설정은 세개가 있습니다. 이러한 설정은 트레이드오프가 있으며 유의하여 사용하여야 합니다.

7.3.1 복제 팩터

replication.factor가 3이라면 각 브로커가 3대의 서로 다른 브로커에 복제됨을 의미합니다. 복제 팩터가 N이면 N+1개의 브로커가 중단되도 토픽의 데이터를 읽거나 쓸 수 있습니다. 하지만 N배의 디스크 공간이 필요하게 됩니다.

따라서 처리량, 지연 시간, 비용, 가용성, 지속성 등 다양한 관점을 고려해 매개변수를 설정해야 합니다.

카프카는 언제나 같은 파티션의 레플리카들을 다른 브로커에 저장합니다. 하지만 이는 충분히 안전하지 않을 수 있습니다. (다른 브로커에 저장하였지만 이들이 같은 랙에 있을 때 랙이 꺼지면 해당 파티션을 사용할 수 없음 따라서 랙 또한 다른 랙으로 잡을것을 권장)

7.3.2 언클린 리더 선출

파티션의 리더가 더 이상 사용가능하지 않을 경우 인-싱크 레플리카 중 하나가 새 리더가 됩니다. 하지만 작동 불능에 빠진 리더 외에 인-싱크 레플리카가 없다면 어떻게 될까요?

어쩔 수 없이 데이터의 손실을 감수하기로 하고 아웃-오브-싱크 레플리카를 리더로 세워야 합니다. 이러한 설정을 unclean.leader.election.enable설정을 통해 관리할 수 있습니다. 기존 설정은 false이며 가장 좋은 신뢰성을 제공하는 만큼 가장 안전한 옵션입니다. 하지만 일부 상황에서 파티션이 복구될 떄까지 사용이 불가능한 상태로 남을 수 있습니다.

데이터 유실을 감수하기로 하고 이 값을 true로 바꾼 뒤 클러스터를 재시작하는 것도 가능합니다.

7.3.3 최소 인-싱크 레플리카

토픽과 브로커 단위 모두 최소 인-싱크 레플리카를 설정할 수 있습니다.

커밋된 데이터를 2개 이상의 레플리카에 쓰고자 한다면, 인-싱크 레플리카의 최소값을 더 높게 잡아줘야 합니다.

7.3.5 디스크에 저장하기

카프카는 세그먼트를 교체할 때 재시작 직전에만 메시지를 디스크에만 플러시하며, 그외의 경우는 리눅스의 페이지 캐시 기능에 의존합니다. 이러한 배경에는 각각 데이터의 복제본을 가지고 있는, 서로 다른 랙이나 가용 영역에 위치한 세 대의 장비가 리더의 디스크에 발생할 가능성은 거의 없기 떄문입니다.

flush.messages 매개변수는 디스크에 저장되지 않은 최대 메시지의 수를, flush.ms는 얼마나 자주 디스크에 메시지를 저장하는지를 조절할 수 있습니다.

7.4 신뢰성 있는 시스템에서 프로듀서 사용하기

프로듀서 또한 신뢰성있도록 설정을 잡아줘야 합니다. 예를 들어

  1. 토픽별로 3개의 레플리카를 가지도록 브로커를 설정 (언클린 리더 선출 false)
  2. 프로듀서가 메시지를 보낼 때 acks=1설정으로 보내도록 설정
  3. 프로듀서가 메시지를 전달할 때 리더에게는 쓰였지만, 레플리카에는 반영되지 않은 상태
  4. commit을 무사히 수행하였고, 레플리카에게 복제를 할 때 리더가 고장남
  5. 다른 레플리카가 리더가 되며 프로듀서가 쓴 메시지는 유실 됨

이를 수정하기 위해서는 신뢰성 요구 조건에 맞는 올바른 acks설정을 사용하거나, 설정과 코드 모두에서 에러를 올바르게 처리해야 합니다.

7.4.1 응답 보내기

프로듀서는 세 가지 응답 모드 중 하나를 선택합니다.

  • acks = 0

파티션이 오프라인이거나, 리더 선출이 진행중이거나, 클러스터가 작동 불능이여도 에러가 발생하지 않습니다. 이는 지연은 낮지만, 종단 지연이 개선되지는 않습니다. (컨슈머는 메시지가 모든 인-싱크 레플리카로 복제되지 않는 한 해당 메시지를 볼 수 없습니다.)

  • acks = 1

리더가 메시지를 받아서 파티션 데이터 파일에 쓴 직후 응답을 합니다. 이는 레플리카로 복제가 완료되기 전에 리더가 정지하거나 크래쉬 날경우 데이터가 유실됩니다.

  • acks = all

리더가 모든 인-싱크 레플리카가 메시지를 받아갈 때 까지 대기합니다. 이는 신뢰성이 가장 높지만, 지연이 길어집니다.

7.4.2 프로듀서 재시도 설정하기

일반적으로 메시지가 유실되지 않는 것이 목표일 경우 가장 좋은 방법은 재시도 가능한 에러가 발생했을 경우 프로듀서가 계속해서 메시지 전송을 재시도하도록 설정하는 것입니다.

  • 재시도 수를 INT.MAX_VAVLUE로 설정(기본 값)
  • 메시지 전송을 포기할 떄까지 대기할 수 있는 시간을 최대로(delivery.timeout.ms)

로 설정할 수 있습니다.

7.5 신뢰성 있는 시스템에서 컨슈머 사용하기

컨슈머는 카프카에 커밋된 데이터만을 읽을 수있습니다. 즉, 모든 인-싱크 레플리카에 쓰여진 다음부터 읽을 수 있습니다. 다르게 말하면, 컨슈머는 일관성이 보장되는 데이터만 읽습니다. 따라서 컨슈머가 할 일은 어디까지 읽었는지 오프셋을 잘 추적하는 일입니다.

컨슈머는 읽어온 오프셋을 커밋통해 저장하며 컨슈머 그룹은 해당 오프셋을 활용해 메시지를 읽습니다.

7.5.1 신뢰성 있는 처리를 위한 컨슈머 설정

  • group.id

컨슈머가 같은 토픽을 구독할 경우, 컨슈머는 해당 토픽전체 파티션의 서로 다른 부분집합이 할당되므로 각 메시지의 다른 부분을 읽게 됩니다. 만약 컨슈머가 구독한 토픽의 모든 메시지를 읽어야 한다면 고유한 그룹ID가 필요합니다.

  • auto.offset.reset

커밋된 오프셋이 없을 때나 브로커에 없는 오프셋을 요청할 때 컨슈머의 행동을 의미합니다. earliest, latest등을 활용하여 컨슈머의 메시지 읽는 위치를 지정할 수 있습니다.

  • enable.auto.commit

자동 커밋여부를 의미합니다.

  • auto.commit.inerval.ms

오프셋을 의해 자동 커밋할 경우 주기를 설정할 수 잇습니다.

7.5.2 컨슈머에서 명시적으로 오프셋 커밋하기

세밀한 제어를 위해 컨슈머가 명시적으로 오프셋을 커밋하고자 한다면 다음과 같은 요소들을 고려해야 합니다.

  • 메시지 처리 먼저, 오프셋 커밋은 나중에

  • 커밋 빈도는 성능과 크래시 발생시 중복 개수 사이의 트레이드오프

  • 정확한 시점에 정확한 오프셋을 커밋하기

  • 리밸런스

  • 컨슈머는 재시도를 해야할 수도 있다

  • 컨슈머가 상태를 유지해야 할 수도 있다.

profile
강단있는 개발자가 되기위하여

0개의 댓글