BackEnd Developer, Love Crossfit, Welcome to Jay's blog

Kafka - 기본 개념 잡기

|

Index

  • 카프카
    • 기본개념
    • 아키텍처
    • Consumer Group
    • Partition Replicas
      • Kafka Replication Factor
      • Leader & Follower
      • ISR (In Sync Replica)
  • 정리
  • References

프로그래머스 웹백엔드 구현 스터디 마지막 주차로 아파치 카프카에 대해 공부하게 되었다.

이름만 들어보았지 실제로 만져보고 스터디해본 적은 처음이어서 이에 대해 정리해보고자 한다.


카프카

기본 개념


카프카는 비동기 처리를 위한 메시징 큐의 한 종류이며, 프로듀서와 컨슈머라는 개념이 등장한다. 대표적인 비동기 메시징 시스템인 메일과 비교하면 이해하기 쉬울 것이다.

메일의 경우, 보내는 사람은 언제든지 메일 서버로 메시지를 보낼 수 있다. 보낸 메시지는 메일 서버에 저장이 되고, 받는 사람은 자기가 원하는 시간에 언제든지 메일을 볼 수 있게 된다.

카프카도 비슷하다. 프로듀서는 카프카로 메시지를 보내게 되고, 그 메시지는 카프카에 저장되어 보관된다. 그리고 컨슈머는 카프카에 있는 메시지를 필요 할때 가져가면 된다.

alt text [출처] https://www.popit.kr/kafka-운영자가-말하는-처음-접하는-kafka/

그리고 카프카는 pub/sub 모델을 지원하는데, 유투브 구독 알림 기능과 비슷하다. 먼저 유저가 관심있는 유투브 채널을 구독하게 된다. 해당 채널의 유투버가 영상을 만들어 유투브에 업로드하게 되면, 유투브 서버는 영상을 저장하고 구독자들에게 새로운 영상이 올라왔음을 알려준다. 알림을 받은 구독자들은 영상을 클릭해 영상을 시청(소비)한다.

카프카도 비슷하다. 컨슈머가 특정 이벤트에 대해 구독을 한 후, 프로듀서가 해당 이벤트를 발생시키면 카프카로 이벤트 메시지를 보낸다. 그 이벤트는 카프카에 저장이 되고, 카프카는 이벤트가 발생되었음을 이벤트 구독자들에게 알린다. 그리고 구독자들은 카프카에 있는 이벤트를 가져와 그에 맞게 소비(ex.디비에 저장, 이메일 발송)하게 된다.


아키텍처


alt text [출처] https://gem1n1.tistory.com/113

카프카는 일종의 메시징 서버이다. 메시지/데이터를 생성하고 기록하는 쪽을 퍼블리셔 또는 프로듀서(Publisher, Producer)라 부르고, 메시지를 가져가는 쪽(Pull)을 컨슈머(Consumer)라 부른다. 메시징 시스템 서버를 중앙에 두고 메시지를 Publish하고 Subscribe 하는 형태의 Pub/Sub 모델을 취하고 있다. 카프카 서버를 브로커(Broker)라 부르며 모든 것은 분산(distributed)되어 있다.(프로듀서, 컨슈머, 카프카)

카프카 클러스터링

모든 메시지를 카프카로 쏘기 때문에 고가용성이 필요하다. 따라서 카프카는 여러개의 서버로 클러스터링 되어 있으며, Master-Slave 구조로 관리해주는 주키퍼 서버가 필요하다.

주키퍼 (Zookeeper)

카프카 클러스터링을 관리해주는 서버. 카프카의 동기화, 리더 채택 등 노드 관리를 해주고, 토픽의 offset 정보 등을 저장하기 위해 필요하다.

  • 0.9 버전이후로 offset을 주키퍼가 아닌 카프카 토픽에 저장하는 방식으로 변경됨

카프카를 다운 받으면 주키퍼가 포함 되어 있다. 카프카 노드 관리를 주키퍼가 하기 때문에 카프카 서버를 시작할 때 주키퍼부터 시작해야 한다.

토픽 (Topic)

카프카 세계에서 메시지는 topic으로 분류되며 토픽 단위로 데이터(메시지)를 저장하고 읽어온다. 따라서 Producer는 특정 토픽을 향해 메시지를 기록해야 한다. 즉, 데이터는 토픽에 저장되고 토픽은 파티션에 분할 그리고 복제되어 있다.

파티션 (Partition)

토픽은 파티션으로 구성되며, 데이터는 파티션 단위로 분산 처리 된다. 한 토픽에 파티션이 3개가 있다면, 3개의 파티션에 대해서 메시지가 분산되어 저장된다. 즉, 메시지는 특정 토픽의 특정 파티션 안에 저장된다.

파티션이 여러 개 있을 경우 데이터는 어디로 저장 될까?
기본적으로 Round-Robin 방식을 따른다. 모듈러 연산을 이용해도 되고 (3으로 나눠서 1,2,3에 넣기), 월단위, 도단위로 파티셔닝 이런식으로 데이터를 분산해서 처리한다.

로그 (Log)

메시지가 카프카로 들어오면, 카프카 내부에서 각 메시지를 로그로 보고 파일 시스템에 기록(commit)한다. 즉, 파티션의 한 칸을 log라 한다. 파티션에 저장될 데이터는 Queue 방식으로 저장되며 파티션 끝에 저장된다. 하나의 파티션 안에서는 순서를 보장해주지만, 파티션 끼리는 메시지 순서를 보장해주지 않는다.

파티션에 한 번 커밋(기록)된 내용은 변경이 불가하다. 주문을 되돌리고 싶다면 주문을 취소하는 커밋을 해야한다. 은행 업무 처리 방식과 동일하다. 토픽, 파티션 자체를 지울 순 있어도 파티션 사용 중 도중에 내용을 바꿀 수는 없다.

alt text [출처] https://gem1n1.tistory.com/113

오프셋 (Offset)

파티션별로 저장된 순서에 따라 인덱스 번호를 가지게 되는데, 이를 카프카에서는 오프셋이라 한다. 카프카는 이 오프셋을 이용해 메시지 순서를 보장한다.

컨슈머의 Offset 포인팅
컨슈머는 어디까지 메시지를 읽었는지 offset으로 카프카에 기록한다. 컨슈머를 재시동하면 처음부터가 아닌 마지막으로 읽었던 위치에서부터 다시 읽어들일 수 있다. offset, partition, topic으로 메시지를 추적하게 된다.


Consumer Group


비슷한 작업을 하는 컨슈머 인스턴스끼리 그룹핑해 놓은 것을 컨슈머 그룹이라 한다.

alt text

  • 컨슈머 그룹 개념을 통해 큐와 pub/sub 모델을 지원한다.
  • 파티셔닝은 컨슈머 그룹마다 한명만 접근 가능하다.
    • 파티션에 대해 한명의 reader만 허용함으로써 데이터를 순서대로 읽어갈 수 있게 하기 위함이다(ordering 보장)
    • 위 사진에서 하나의 토픽은 3개의 파티션으로 구성된다. 메시지가 특정 파티션에 들어가면 새 메시지는 모든 컨슈머 그룹에 브로드 캐스트 되고, 모든 커슈머 그룹은 해당 파티션에 써진 메시지를 읽어간다.
    • 하지만, 하나의 그룹 안에서는 하나의 컨슈머만의 해당 메시지를 읽는다.
  • 컨슈머 그룹 A에 새로운 A4가 추가되었다. A4는 어느 파티션을 읽을까?
    • 아무것도 안 읽는다. 대신 다른 컨슈머가 죽으면 대신 처리하는 역할을 한다. 아무도 안 죽으면 가만히 있는다.
    • 그룹 B처럼 컨슈머가 1개만 있는 경우 3개를 모두 다 읽어간다. 죽으면 해당 그룹에서는 아무것도 안한다.
  • 실제로 구성할 때는 하나의 컨슈머 그룹안에 몇개의 인스턴스를 들고 갈지 테스트를 해보고 적정한 값으로 구성해야 하며 그룹 내 어떻게 분산을 할 건지 고민이 필요하다.
  • 그룹 내 각 노드들은 서버 또는 쓰레드 등 다양한 방식으로 구성 가능하다.
  • 그룹 내 하나의 노드가 죽으면 파티션 재분배(rebalance)가 일어나며, 서로의 offset을 그룹 안에서 서로 공유하고 있기 때문에 죽은 노드의 작업을 다른 노드가 이어갈 수 있게 된다.

alt text [출처] https://victorydntmd.tistory.com/344?category=798367

컨슈머 그룹의 목적

그런데 컨슈머는 왜 개별적으로 사용하지 않고 그룹핑해서 사용할까?

첫번째는 가용성 때문이다. 하나의 그룹안에 여러대의 서버를 둠으로써, 특정 노드에 장애가 발생했을 때 다른 노드가 그 작업을 이어가는 파티션 재분배(rebalancing)이 일어난다. 가능한 이유는 같은 그룹 안에 있는 컨슈머끼리는 서로의 파티션 offset 정보를 공유하면서 메시지를 소비하기 때문이다 따라서 이러한 fail over 기능을 통해 서비스를 지속적으로 제공 가능하게 된다.

두번째 이유는 컨슈머별로 파티션 메시지를 순차적으로 읽어갈 수 있음을 보장하기 위함이다. 만약 컨슈머 그룹이 없다면 카프카에서는 컨슈머들을 구분 할 수가 없다. 그 결과 하나의 파티션에 2개의 컨슈머가 동시에 접근한다면 어떤 컨슈머가 몇 번의 offset 부터 소비해야 하는지 알 수 없게 된다. 즉, 순서를 보장할 수 없게 된다.

하지만 컨슈머 그룹이 있다면 카프카는 그룹 별로 서로 다른 offset을 유지할 수 있게 되고 각 그룹들은 자신의 그룹에 대한 offset 정보(파티션별 offset)를 관리할 수 있게 된다. 그리고 하나의 파티션은 그룹별 하나의 컨슈머만이 접근할 수 있도록 관리한다.


alt text [출처] https://dzone.com/articles/kafka-consumer-architecture-consumer-groups-and-su

Partition Replicas

파티션의 “백업”. 데이터 손실 방지를 위해 존재한다.

Kafka Replication Factor

bin/kafka-topics.sh –create –zookeeper localhost:2181 –replication-factor 3 –partitions 2 –topic event

--replication-factor 옵션을 이용하면 replication 수를 지정할 수 있다.

위 코드는 event라는 topic을 생성하는 명령어이다. 파티션 3, replica 2를 주면 동일한 내용의 파티션이 2개씩 생성되어 총 6개(2*3)의 파티션이 생성된다.

  • zookeeper가 파티션을 브로커에 골고루 분배해준다
  • 파티션이 한개면 replica를 줄 수 없게 된다.

Leader & Follower

카프카의 세계에서는 복제본을 leader와 follower로 나눈다. Read/Write는 오직 리더하고만 이루어지고, 팔로워는 주기적으로 리더의 데이터를 보며 복제만 한다.

alt text [출처] https://www.popit.kr/kafka-운영자가-말하는-topic-replication/

topic01는 하나의 leader, 하나의 follower로 구성되어 있고, topic02는 하나의 leader와 두 개의 follower로 구성되어 있다. topic01을 향해 메시지를 쏘게 되면, leader 파티션이 존재하는 Broker1에 메시지가 생성된다. follower인 Broker2에 존재하는 Partition은 leader를 복제함으로써 데이터 정합성을 이룬다.

만약 리더가 있는 브로커가 장애가 난다면 남은 팔로워 중에 하나가 리더로 선출되는데, 이때 데이터 정합성을 유지하기 위해 등장한 개념이 카프카의 ISR이다.

  • 리더 선출은 zookeeper가 해준다.

ISR (In Sync Replica)

alt text [출처] https://www.popit.kr/kafka-운영자가-말하는-topic-replication/

ISR은 현재 리플리케이션 되고 있는 리플리케이션 그룹(replication group)을 의미한다. 먼저 우리가 topic을 만들게 되면, topic이 생성되고 설정한 replication factor 수에 맞추어 위와 같이 ISR이 구성된다.

ISR 규칙 중 하나는 같은 ISR에 속한 구성원만이 리더 자격을 가질 수 있다. 그렇기 때문에 리더가 죽으면 follower 중 하나가 리더가 될 수 있는 것이다. 그런데 이러한 failover 기능은 leader와 follower간의 동기화가 잘 되어 있어야 가능하다.

그러므로 ISR이 구성되면 leader는 follower들이 주기적으로 데이터를 확인하고 있는지 확인해서, 설정된 일정 주기보다 뒤쳐지면 리더가 될 자격이 없다 판단해 ISR 그룹에서 팔로워를 추방해 리더 자격을 박탈시킨다. 따라서 follower는 리더와 동일한 데이터를 유지하기 위해 짧은 주기로 leader로 부터 데이터를 가져오게 된다. 이렇게 동일한 ISR 내에서 리더와 팔로워는 주기적으로 데이터 정합성을 맞추게 되어 리더가 죽어도 다른 팔로워가 리더의 일을 해낼 수 있게 된다.

alt text [출처] https://log-laboratory.tistory.com/m/234?category=1109284

References

프로그래머스 웹백엔드 구현 스터디 7기 내용
https://www.popit.kr/kafka-운영자가-말하는-처음-접하는-kafka/
https://www.popit.kr/kafka-consumer-group/
https://gem1n1.tistory.com/113
https://medium.com/@umanking/카프카에-대해서-이야기-하기전에-먼저-data에-대해서-이야기해보자-d2e3ca2f3c2
https://www.popit.kr/kafka-운영자가-말하는-topic-replication/
https://log-laboratory.tistory.com/m/234?category=1109284
https://ooeunz.tistory.com/136