Lib/KAFKA

실전카프카 개발부터 운영까지 - 4장. 카프카의 내부 동작 원리와 구현

FreeEnd 2022. 10. 3. 13:15
반응형

이 블로그는 실전카프카 개발부터 운영까지 (책만) 책 내용을 스터디를 위해 정리 한 내용 입니다.

책구매는 바로가기 에서 구매 가능합니다.

이번 장에서는 카프카 내부동작 원리와 구현중에서 가장 중요한 부분중 하나인 리플리케이션 동작에 대해서 공부 한다.

 

카프카 리플리케이션

카프카는 높은 고가용성을 제공하기 위해서 여러개의 브로커중 한 두개에서 장애가 발생 하더라도, 안정적인 서비스가 가능하도록 리플리케이션 서비스을 제공 한다. 

 

Kafka Replication document link : https://kafka.apache.org/documentation/#replication

 

리플리케이션 동작 개요

 리플리케이션이란 서비스 장애에 대비하여 데이터가 유실 되지 않도록 자신의 데이터를 다른곳으로 백업 하여 복구에 대비하는 기능을 말한다.

카프카에서는 메시지가 백업 대상이지만, 메시지 (토픽) 자체를 백업하는게 아니라 파티션을 리플리케이션 한다. 

 이 기능은 replication factor 라는 옵션을 이용한다.

 

kafka-topics.sh --bootstrap-server $KAFKA_SERVER_INFO --create --topic $TOPIC_NAME --partition 1 --replication-factor 3
  • --partition 1 : 파티션 개수를 1개로 지정한다
  • --replication-factor 3 : 리플리케이션 팩터수를 3개로 지정한다.

 

 이렇게 TOPIC 을 생성하면 파티션 1개를 가진 TOPIC 이 생성되며, 이때 이 파티션을 리플리케이션 하는 팩터가 3개 지정된다. 결국 메시지를 하나 생성하면 카프카를 구성하는 다른 브로커 2개에 대해서 메시지를 동일하게 복제 하여 관리 하게 된다.

 

파티션의 리더와 팔로워

high availability with kafka : https://jack-vanlightly.com/blog/2018/9/2/rabbitmq-vs-kafka-part-6-fault-tolerance-and-high-availability-with-kafka

Fig 1. Four partitions distributed across three brokers.

리플리케이션이 지정된 토픽은 리더(leader) 와 팔로워(follower) 로 지정되어 각자의 역할을 수행한다.

리더(leader)는 모든 프로듀서 및 컨슘머의 메시지 생성, 수신을 담당한다. 

팔로워(follower) 는 리더가 수신한 메시지를 지속적으로 자신에 복제 한다.

 

팔로워는 메시지를 직접 송/수신 하지 않는다. 메시지 송수신은 모두 리더가 담당하며, 팔로워는 리더가 수신한 메시지를 자신에게 복제만 한다. 그리고 리더가 장애가 발생 할 경우 자신이 리더가 된다. (fig 2의 partition 2)

Fig 2. Broker 3 dies and the partition 2 follower on broker 2 is elected the new partition leader.

 리발란싱

파티션 리더가 하나의 브로커에만 몰려 있을경우 서버 운영면에서 비 효율 적일 수 있다. 이때 rebalancing 옵션을 이용하며 다시 리더가 적절하게 다양한 브로커로 분산 되게 설정 할 수 있다.

 

  • 토픽 옵션에  auto.leader.rebalance.enable=true 을 주면 자동으로 리발란싱을 수행한다.
  • 옵션을 설정하지 않았다면 kafka-preferred-replica-election.sh 명령어를 이용해 리발란싱을 수행 할 수 있다.

 

 fig2 그림 에서 broker3 가 다시 살아나게되면, 각 프로커에 적당히 리더가 위치 되도록 rebalacing 이 일어나서 fig 1 그림처럼 다시 리더가 적절히 분배 된다. 

 

복제 유지와 커밋

 리더와 팔로워는 "In Sync Replicas" 라는 논리적 그룹으로 묶여있다. 이 그룹은 하나의 리더와 0개 이상의 팔로워로 구성된다. 이 그룹 안에서 각각의  팔로워(follower) 들은 리더(leader) 의 마지막 메시지를 수신한다. 또 리더에 장애가 발생하면 이 그룹안의 하나의 팔로워가 새로운 리더가 된다.

 

 팔로워는 이때 ISR 그룹에서 제거된다.

  • replica.lag.time.max.ms 에 설정된 시간 이내에 fetch 요청 (복제요청) 을 하지 않았을 경우. (팔로워가 죽었을경우)
  • replica.lag.time.max.ms 에 설정된 시간보다 요청 시간이 느릴경우.

 

 

이 ISR 그룹 안에서 데이터가 모두 복제 되면 리더는 메시지를 커밋하고, 이 커밋을 하이워터마크 (high water mark) 라고 부른다. 이렇게 모든 팔로워에 저장이 완료되었을 경우에만 컨슘머가 메시지를 읽어 갈 수 있다.

 

 각 팔로워들의 커밋된 오프셋은 replication-offset-checkpoint 라는 파일에 저장 되어 있다.

 

리더와 팔로워의 단계별 리플리케이션 동작

 리플리케이션시 리더가 팔로워에게 메시지를 전송(push) 하는것이 아닌, 팔로워가 리더에게 신규 메시지를 요청(pull) 한다. 이는 리더의 ack 관리를 줄여 성능을 높이기 위함이다.

 

 

  1. 리더가 message-1 을 수신한다.
  2. 팔로워들은 리더에게 message 요청(fetch) 를 보낸다.
  3. 리더로부터 수신한 message-1 을 자신에게 기록후, 다시 리더에게 message-2 요청을 보낸다.
    1. 일부 팔로워들이 message-1 을 요청할 경우, 리더는 하이워터마크를 업데이트 하지 않는다.
    2. 모든 팔로워들이 message-2 를 요청했을 경우, 리더는 message-1 이 모든 팔로워들에게 수신 되었다고 생각하고 내부 하이워터마크를 message-1 의 오프셋 0 으로 업데이트 한다.

 

리더에포크와 복구

 리더에포크 (leader Epoch) 는 파티션이 복구될 경우, 일관성을 유지 하기 위한 용도로 사용된다.

컨트롤러에의해 관리되는 32비트 코드이다.

 리더에포크는 브로커 장애후 복구시, 리더에게 리더에포크 메시지를 보내어  현재 리더의 메시지와 오프셋정보를 받아 자신의 메시지와 하이워터마크를 업데이트 하여 리더와의 데이터 동기화를 진행한다.

 

컨트롤러

 컨트롤러는 파티션 세트를 모니터링 하고 있다가 리더에 장애가 발생하면 해당 ISR 그룹중에 하나를 리더를 선출 한다.
가용성 보장 정보는 주키퍼 내에서 관리 된다.

 

장애 발생시 리더 선출 과정

  1. 주키퍼가 모니터링 하고 있는 브로커 1번에 장애가 발생함을 감지한다.
  2. 주키퍼는 장애가 발생한 브로커의 파티션에 문제가 발생함을 인지한다.
  3. 컨트롤러는 주키퍼 워치를 통해 0번 파티션의 장애를 인지하고, isr중 하나를 새로운 리더로 선출한다.
  4. 컨트롤러는 주키퍼에 새로운 리더정보를 기록한다.
  5. 컨트롤러는 이렇게 갱신된 정보를 모든 정보를 모든 브로커에게 전파 한다.

 

정상스러운 과정에서의 리더 변경과정

  1. 관리자가 리더가 포함된 브로커에 종료 명령을 실행해 종료 신호를 브로커에 전달 (SIG_TERM) 한다.
  2. 종료 신호를 받은 브로커는 컨트롤러에 종료를 알린다.
  3. 컨트롤러는 새로운 리더를 선출하고, 해당 정보를 주키퍼에 전달한다.
  4. 컨트롤러는 새로운 리더 정보를 모든 브로커에 전파한다.
  5. 컨트롤러는 종료 명령을 수행한 브로커에게 정상 종료를 허락한다.
  6. 응답을 받은 브로커는 캐시 내용을 저장하고 종료한다.

 

로그(로그 세그먼트)

카프카 메시지는 세그먼트에 저장이 된다. 이 세그먼트는 메시지의 키, 값, 오프셋 등의 정보와 함께 저장한다.

이 세그먼트는 파일이 너무 커져버리면 관리가 어렵기때문에 파일의 크기를 적당한 수준에서 나누어 관리한다.

기본은 1GB 이며, 지정된 크기 기준으로 나누어 관리 할수 있다.

 

 지정된 크기에 도달 하게 되면 해당 파일은 CLOSE 가 되고, 새로운 파일을 생성한다. 

로그세그먼트 삭제

로그 세그먼트 삭제옵션은 server.properties 에 log.cleanup.policy=delete 로 명시 되어야 한다. default 는 delete 이므로 지정하지 않았다면 삭제 정책이 적용된다.

 

  • --add-config retention.ms=$MICRO-SECOND

지정된 시간이 지난뒤 로그 세그먼트는 삭제되며, 5분 주기로 파일의 생성 시간을 체크 한다.

그러므로 0으로 설정 시, 매 체크 순간 삭제되게 된다.

아무것도 지정하지 않으면 카프카 기본 설정값인 7일이 지정되게 된다.

 

 

로그세그먼트 컴팩션

 로그 컴팩션은  메시지의 키값을 기준으로 마지막 데이터만 보관한다. 단, 현재 활성화된 세그먼트는 제외하고 나머지에 대해서만 수행 된다.

 

 이 로그세그먼트 컴팩션은 결국 해당 키에 해당하는 값 중이 메시지 발생에 따라 일부만 관리 하는 메시지가 아닌, 항상 전체의 값을 관리 하는 방식에 대해서만 사용할 수 있다.

 로그 컴팩션은 최종 값만 보관하게 되므로 복구가 빠르고, 저장되는 데이터를 최소화 하여 관리 할 수 있다.

반응형