Kafka 기본 개념 및 용어 정리

땡글이·2023년 3월 9일
0

Kafka 에 대하여

목록 보기
1/5
post-thumbnail

Kafka가 어떤 부분에서 뛰어난지에 대해 알아보기에 앞서, 어떤 기능들과 어떤 개념들이 존재하는지 간단하게 정리해본다.

Kafka 기본 개념 및 용어

토픽(Topic)

Kafka 에서는 데이터가 들어가는 공간을 토픽이라고 한다. 또한, 하나의 Kafka에서는 여러 개의 토픽을 생성할 수 있다. 프로듀서는 카프카에 데이터를 넣고, 컨슈머는 데이터를 가져가는 구조이다.

또한, 하나의 토픽은 여러 개의 파티션(partition)으로 구성될 수 있다. (파티션 번호는 0번부터 시작한다) 프로듀서가 데이터를 넣고 컨슈머는 파티션에 있는 데이터를 읽는다. 하지만, 카프카에 있는 데이터를 읽는다고 기존 데이터가 삭제되지 않는다는 특징 을 가진다.
즉, Consumer가 record들을 가져가도 데이터는 삭제되지 않는다! 그렇기에 새로운 Consumer가 해당 파티션에 있는 Record를 가져가려 하면, 0번부터 가져갈 수 있는 것이다.

  • 하지만, 새로운 컨슈머가 0번부터 메시지를 가져가려면, 컨슈머 그룹이 달라야 하고, auto.offset.reset=earliest여야 한다는 전제조건이 붙는다.

만약 파티션이 여러 개라면, 프로듀서가 토픽에 데이터를 저장할려고 할 때 데이터는 어느 파티션에 저장될까?

  • key 값을 null 로 지정하지 않고 기본 파티셔너를 사용할 경우 토픽에 메시지를 저장할 때, 라운드 로빈(Round robin) 방식으로 파티션에 메시지가 저장된다.
  • key 값을 명시하고, 기본 파티셔너를 사용하면 키의 해시 값(hash) 을 구하고, 특정 파티션에 데이터를 할당한다.

파티션은 늘리는 것은 가능하지만, 파티션의 개수를 줄이는 것을 불가능하니 주의해야 한다.

왜 파티션 개수를 늘릴까?

파티션을 늘리면, 컨슈머의 개수를 늘려서 데이터 처리를 분산시킬 수 있기 때문이다.

Partition의 Record는 언제 삭제되는가?

  • log.retetion.ms : 최대 record 보존 시간
  • log.retention.byte : 최대 record 보존 크기(byte)

브로커(Broker)

카프카 브로커(Broker)는 카프카가 설치되어 있는 서버 단위를 말한다. 보통 3개 이상의 브로커를 구성하여 카프카를 운영하는 것을 권장한다.

복제(Replication), ISR(In-Sync-Replication)

카프카의 가용성 을 보장하기 위해, 복제(Replication)을 많이 사용한다. 만약 원본에서 문제가 생기면, 복제본이 원본 역할을 승계하게 됨으로써 SPOF(Single-Point-Of-Failure) 장애에 대응 가능해진다.

  • replication : 1 = 원본 1개만 존재
  • replication : 2 = 원본 1개와 복제본 1개 존재
  • replication : 3 = 원본 1개와 복제본 2개 존재

브로커의 개수에 따라, replication의 개수는 제한된다. 브로커의 개수가 3이면, replication은 4 이상이 될 수 없다.

여기서 원본 1개의 partition은 Leader Partition 이 되고, 복제본의 partition은 Follower Partition 이 된다.

Leader Partition의 역할

프로듀서는 토픽의 파티션에 데이터를 전달할 때, 전달받는 주체가 Leader Partition이 된다.

ack 옵션

프로듀서에는 ack라는 옵션이 있는데, ack 옵션 값에는 0, 1, all 3개 중 하나를 골라 사용한다.

  • ack : 0 = Leader Partition에 데이터 전송 후 응답 값 받지 않는다.
    • 속도는 빠르지만 데이터 유실 가능성 있다.
    • Leader Partition에 데이터가 정상적으로 전송됐는지 확인할 수 없고, 나머지 Partition에 복제가 잘 이뤄졌는지도 확인 불가능하다. (UDP 프로토콜과 유사)
  • ack : 1 = Leader Partition에 데이터 전송 후 응답 값 받는다.
    • Leader Partition이 데이터를 받은 즉시 브로커에서 장애가 난다면, 나머지 Partition에서 복제 됐는지 알 수 없어서 이 방법 또한 데이터 유실 가능성 있다.
  • ack : all = Leader Partition에 데이터 전송 후 응답 값 받고, Follower Partition에서도 응답 값을 받는다.
    • 속도는 느리지만, 데이터 유실 가능성이 없다

Follower Partition의 역할

Leader Partition에서 문제가 생기면, Follower Partition이 Leader Partition의 역할을 승계한다.

주의할 점

replication 개수가 너무 많아지면, 그만큼 브로커의 리소스 사용량도 늘어나게 돼서 카프카에 들어오는 데이터량과 저장시간(retention date)를 잘 고려해서 replication 개수를 정해야 한다.

Leader PartitionFollower Partition 들을 합쳐서, ISR(In-Sync-Replication) 이라고 부른다.

파티셔너(Partitioner)

프로듀서가 데이터를 보내면 무조건 파티셔너(Partitioner)를 통해서 브로커로 데이터가 전송된다. 파티셔너는 데이터를 어느 파티션에 데이터를 넣을지 결정한다.

  • 레코드의 메시지 키와 값에 따라서 파티션의 위치가 결정된다.

프로듀서를 사용할 때, 카프카의 파티셔너 설정을 따로 하지 않는다면, UniformStickyPartitioner 로 설정이 된다.
이 파티셔너는 메시지 키가 있을 때와 없을 때 다르게 동작한다. 아래에서 살펴본다.

메시지 키를 가지는 레코드

메시지 키를 가지는 레코드는 파티셔너에 의해서 특정한 해쉬값이 생성된다. 이 해쉬값을 기준으로 어느 파티션에 들어갈지 결정된다.

  • 동일한 메시지 키를 가진 레코드는 동일한 해시값을 생성해내서, 동일한 파티션에 들어가는 것을 보장한다.
  • 그렇기에 순서를 지켜서 처리할 수 있다는 장점 이 있다.

메시지 키가 없는 레코드

메시지 키가 없는 레코드는 라운드-로빈 방식으로 파티션에 레코드가 저장된다.
UniformStickyPartitioner는 전통적인 라운드-로빈 방식과는 조금 달리 동작한다. UniformStickyPartitioner 는 프로듀서에서 배치로 모을 수 있는 최대한의 레코드들을 모아서 파티션으로 데이터를 보내게 된다.

  • 이렇게 배치단위로 데이터를 보낼 때, 라운드로빈 방식으로 돌아가면서 데이터를 넣게 된다.

기본 파티셔너와 다른 파티셔너를 원한다면, 카프카에서 제공하는 Partitioner 인터페이스를 구현해 직접 커스터마이징한 파티셔너를 사용할 수도 있다.

컨슈머 랙(Consumer Lag)

컨슈머 랙(Consumer Lag) = 카프카 Lag 은 카프카를 운영함에 있어서 아주 중요한 모니터링 지표 중 하나이다.

컨슈머 랙(Consumer Lag)은 컨슈머가 마지막으로 읽은 offest과 프로듀서과 마지막으로 넣은 offset의 차이를 말한다.

데이터의 offest은 프로듀서가 데이터를 넣을 때 결정된다.

lag의 숫자를 통해 현재 해당 토픽에 대해 파이프라인으로 연계되어 있는 프로듀서와 컨슈머의 상태를 유츄할 수 있다. 주로 컨슈머의 상태를 볼 때 사용한다.

  • lag 값이 크다 : 컨슈머가 읽는 속도가 프로듀서가 넣는 속도에 비해 느리다.
  • lag 값이 적다 : 컨슈머가 읽는 속도가 프로듀서가 넣는 속도와 거의 비슷하다.

토픽에 여러 파티션이 존재하면 여러 Lag이 존재할 수 있다. 한 개의 토픽과 컨슈머 그룹에 대한 lag이 여러 개 존재할 때, 그 중 가장 높은 숫자의 lag을 records-lag-max 라고 부른다.

Burrow - Consumer lag 모니터링 오픈소스

카프카 Lag은 토픽의 가장 최신 오프셋과 컨슈머 오프셋 간의 차이이다. Kafka-client 라이브러리를 사용해서 Java 또는 Scala 언어를 통해 카프카 컨슈머를 쉽게 구현가능하다. 구현한 카프카 컨슈머를 통해 현재 Lag 정보를 가져올 수 있다.

만약, lag을 실시간으로 모니터링하고 싶다면 데이터를 Elasticsearch나 InfluxDB와 같은 저장소에 넣은 뒤, Grafana 대시보드를 통해 확인할 수 있다.

하지만, 컨슈머 단위에서 lag을 모니터링하고 운영하는 것은 아주 위험하고 운영요소가 많이 들어간다.

왜냐하면, 컨슈머 로직 단에서 lag을 수집하는 것은 컨슈머 상태에 디펜던시가 걸리기 때문이다. 컨슈머가 비정상적으로 종료되면, 더이상 컨슈머는 lag정보를 보낼 수 없어서 lag을 수집하고 모니터링할 수 없다.

또한, 컨슈머가 개발될 때마다 해당 컨슈머에 lag 정보를 특정 저장소에 저장할 수 있도록 로직을 개발해야 한다. 만약 컨슈머 lag을 수집할 수 없는 컨슈머라면, lag을 모니터링 할 수 없으므로 운영이 매우 까다로워진다.

그래서 카프카의 컨슈머 lag을 효과적으로 모니터링할 수 있는 오픈소스인 Burrow를 사용해야 한다.

Burrow의 주요 3가지 특징

멀티 카프카 클러스터 지원

카프카 클러스터가 여러 개 있어도, Burrow 어플리케이션 하나만 연동해도 카프카 클러스터에 붙은 컨슈머의 lag을 모두 모니터링할 수 있다.

Sliding window를 통한 Consumer의 status 확인

Burrow에선, Consumer의 status를 ERROR, WARNING, OK로 표현한다.

  • 만약 데이터 양이 일시적으로 많아지면, consumer offset이 증가하게 되면 WARNING으로 정의된다.
  • 만약 데이터가 많아지는데 컨슈머가 데이터를 읽지 않으면 ERROR로 정의해서 컨슈머가 문제가 있는지 알 수 있다.

HTTP API 제공

앞의 정보들을 모두 HTTP API를 통해 조회 가능하다.

Kafka 와 RabbitMQ, Redis queue와의 차이

위처럼 메시징 플랫폼으로 불리는 것들(Kafka, RabbitMQ, Redis Queue)은 2가지로 나뉜다. 하나는 메시지 브로커, 다른 하나는 이벤트 브로커 이다. RabbitMQ와 Redis Queue는 메시지 브로커에 해당하고, Kafka는 이벤트 브로커에 속한다.

메시지 브로커는 이벤트 브로커로서의 역할을 수행할 수 없지만, 이벤트 브로커는 메시지 브로커의 역할을 수행할 수 있다.

메시지 브로커는 대규모 메시지 기반 미들웨어 아키텍처에서 사용되어 왔다.

메시지 기반 아키텍처와 이벤트 기반 아키텍처

메시지 기반 미들웨어 아키텍처(Message-Oriented Middleware Architecture) 는 분산 시스템에서 애플리케이션 간 통신을 위해 메시지 큐를 사용하는 아키텍처이다. 이 아키텍처에선 메시지 큐가 미들웨어 역할을 수행하여 애플리케이션 사이의 비동기식 통신을 관리한다.
이벤트 기반 미들웨어 아키텍처(Event-Driven Middleware Architecture) 는 이벤트를 중심으로 애플리케이션 간 통신을 구성하는 아키텍처이다. 이벤트는 시스템 내에서 발생하는 모든 상황을 의미하며, 이를 기반으로 애플리케이션은 이벤트를 감지하고 이에 대한 응답으로 동작한다. 메시지 기반 아키텍처와 유사하지만, 이벤트가 중심이 되므로 이벤트에 대한 응답으로 애플리케이션이 동작하는 것이 특징이다. 이 아키텍처는 실시간성이 중요한 분야에서 많이 사용된다..

메시지 브로커에 있는 메시지를 받아서 적절히 처리하고 나면, 즉시 또는 짧은 시간 내에 삭제되는 구조이다. 반면에 이벤트 브로커는 이와는 다르다.

  • 이벤트 또는 메시지라 불리는 것은 레코드를 의미한다.

이벤트 브로커의 특징

레코드를 보관하고 인덱스를 통해 개별 액세스를 관리

메시지 브로커는 메모리에 메시지를 저장하기에 휘발성이다. 하지만, 이벤트 브로커는 디스크에 레코드를 저장함으로써 영구적으로 저장할 수 있다.
또한 레코드를 검색할 때, 인덱스를 이용함으로써 검색 속도를 향상시킨다.

업무상 필요한 시간동안 이벤트 보존 가능

즉, 차이점을 정리하면 메시지 브로커는 메시지를 받고나면 메시지를 삭제하지만, 이벤트 브로커는 삭제하지 않는다.

메시지를 삭제하지 않는 이유

이벤트 브로커는 서비스에서 나오는 이벤트를 마치 데이터베이스에 저장하듯이 이벤트 브로커의 큐에 저장한다. 이렇게 했을 때의 이점이 존재한다.

  • 한 번 일어난 이벤트 데이터를 브로커에 저장함으로써 단일 진실 공급원으로 사용할 수 있다.
  • 장애가 발생했을 때, 장애가 일어난 지점부터 재처리할 수 있다.
  • 많은 양의 실시간 스트림 데이터를 효과적으로 처리할 수 있다는 특징을 가진다.

Reference

데브원영 - 아파치 카프카
https://jiming.tistory.com/332

profile
꾸벅 🙇‍♂️ 매일매일 한발씩 나아가자잇!

0개의 댓글