이번에는 kafka의 주요 component에 대해 알아본다.

Producer, Consumer

image

중간에 있는 kafka에 클러스터가 있고, 그 안에 topic이라는 것을 만든다. topic은 kafka 안에서 메세지가 저장되는 장소이다. producer 어플리케이션은 메세지를 만들어서 topic으로 보내주는 역할을 하고, consumer는 kafka topic 내에 들어있는 메세지를 가져가서 활용하는 어플리케이션이다.

  • Topic: kafka 안에서 메시지가 저장되는 장소
  • Producer: 메시지를 생산(Produce)해서 Kafka의 Topic으로 메시지를 보내는 애플리케이션
  • Consumer: Topic의 메시지를 가져와서(polling) 소비(Consume)하는 애플리케이션

consumer들을 consumer group이라고 하는 집합 형태로 사용된다. 하나의 Consumer는 하나의 Consumer Group에 포함되며, Consumer Group내의 Consumer들은 협력하여Topic의 메시지를 분산병렬 처리한다. 즉, Consumer Group은 Topic의 메시지를 사용하기 위해 협력하는 Consumer들의 집합이다.

Producer와 Consumer 의 동작 방식

image

Producer와 Consumer는 서로 알지 못한다. (sync 방식이 아님) 다시말해 누가 받는지 누가 보내는지 알지 못하는 상태로 동작한다. 따라서 Producer와 Consumer는 각각 고유의 속도로 Commit Log 라는 공간에 Write 및 Read를 수행한다.

다른 Consumer Group에 속한 Consumer들은 서로 관련이 없으며, Commit Log에 있는 Event(Message)를동시에 다른 위치에서 Read할 수 있다. 물론 같은 공간에서 읽는 것도 가능하다.

Commit Log

commit log는 추가만 가능하고 변경이 불가능한 데이터 스트럭처이다. 데이터(Event)는 항상 로그 끝에 추가되고 변경되지 않는다.

Offset은 Commit Log 에서 Event의 위치를 말한다. 아래 그림에서는 0부터 10까지의 Offset이 존재한다.

image

producer가 write 하는 맨끝 commit log의 위치를 LOG-END-OFFSET이라고 한다. Consumer가 내가 여기까지 읽어갔다고 표시 (commit)을 하는 commit log의 위치를 CURRENT-OFFSET 라고 한다. 이 두개 offset의 차이를 consumer lag 이라고 한다. 다시말해 Producer가 Write하는 LOG-END-OFFSET과 Consumer Group의 Consumer가 Read하고 처리한 후에 Commit한 CURRENT-OFFSET과의 차이(Consumer Lag)가 발생할 수 있다.

Topic, Partition, Segment

image

Topic은 kafka 안에서 메세지가 저장되는 장소라고 했다. 눈에 보이지 않고 파일이나 디렉토리로 표시되지 않는 논리적인 표현이다.

partition은 방금 공부했던 commit log이다. 하나의 topic은 하나 이상의 partition으로 구성되고, 병렬처리를 위해 다수의 partition을 사용하여 처리량을 향상시킨다. partition 부터는 실제로 우리 눈에 파일이나 디렉토리 형태로 보인다. Topic을 생성할 때 partition의 개수를 정해야 한다.

partition은 segment 라고 하는 물리 파일로 구성되어 있다. 메시지(데이터)가 저장되는 실제 물리 파일은 segment 인 것이다. Segment File은 지정된 크기보다 크거나 지정된 기간보다 오래되면 새로운 파일이 열리고 메시지는 새 파일에 추가된다.

image

Topic을 생성할 때 partition의 개수를 정해야 하는데, 각 partition은 broker 들에게 분산되며 segment file 들로 구성된다. kafka cluster는 여러개의 broker들로 구성되어 있다. 이 broker 들을 나중에 확장이나 축소가 가능하다.

예를 들어 topic을 만들때 partition을 3개로 하겟다고 하면 위의 그림처럼 partition 3개가 broker들에게 분산이 되면서 만들어 진다. 또 다른 topic을 만드는 데 partition을 3개로 한다고 하면 또다시 partition 3개가 broker들에게 분산이 되면서 만들어 진다. parition이 분산되는 방식은 broker cluster 내에서 최적화하여 최적의 곳에 partition을 위치 시켜준다.

partition 안에는 여러개의 segment 파일이 존재한다. segment 파일은 rolling strategy를 사용하여 분리 및 생성되는데, rolling strategy는 특정 용량(default 1GB)을 초과하거나 특정 시간(default 168 hours)을 넘어가면 새로운 파일을 만드는 형식이다. 이를 해석하면 partition 당 오직 하나의 segment가 활성화 되어 있다는 말이다. 새로운 메세지가 전송되면 마지막 segment에만 데이터가 추가된다.

image

정리

image

  • Topic 생성 시 Partition 개수를 지정
    • partition 개수는 변경이 가능하지만 운영시에는 변경을 권장하지 않음
    • Partition 번호는 0부터 시작하고 오름차순
  • Topic 내의 Partition들은 서로 독립적임
  • Event(Message)의 순서는 하나의 Partition 내에서만 보장
  • Event(Message)의 위치를 나타내는 offset이 존재
  • Offset은 하나의 Partition에서만 의미를 가짐 (partition 자체가 다른 의미 이기 때문)
  • Partition 0의 offset 1 ≠ Partition 1의 offset 1
  • Offset 값은 계속 증가하고 0으로 돌아가지 않음
  • Partition에 저장된 데이터(Message)는 변경이불가능(Immutable)
  • Partition에 Write되는 데이터는 맨끝에 추가되어 저장됨
  • Event(Message)의 순서는 들어온 순서 그대로 적재됨
  • Partition은 Segment File들로 구성됨
  • segment file은 너무 커지는 것을 방지하기 위해 rolling 정책으로 생성됨
  • Rolling 정책: log.segment.bytes(default 1 GB), log.roll.hours(default 168 hours)