Producer
는 메세지를 생산하는 주체이다. 메세지를 만들고 Topic에 메세지를 전송한다. Producer는 Consumer의 존재를 알지 못한다.
여러 partition을 쓰는 이유는 분산 저장을 하기 위해서다. 하나의 파티션만 있다면 몇 천건의 메시지가 동시에 카프카에 쓰여질때 시간이 오래 걸릴 수 있다. 데이터가 하나의 파티션에 순차적으로 append되는 방식이기 때문이다.
Partition
은 브로커 내에서 로그 파일로 저장된다. 파티션 내 메시지는 고유한 오프셋(offset)을 가지며, 이는 파티션에서의 순서를 나타낸다. 오프셋은 파티션 내에서만 고유하며, 다른 파티션 간에는 중복될 수 있다.
Broker
는 카프카의 서버를 칭한다. broker_id
를 지정함으로써 동일한 노드내에서 여러 개의 broker 서버를 띄울 수 있다.
zookeeper
는 Kafka 2.8 이전까지 브로커 메타데이터 관리와 리더-팔로워 선출을 담당했다. Kafka 2.8 이후에는 KRaft(Kafka Raft) 모드가 도입되어 ZooKeeper 없이 Kafka 클러스터를 관리할 수 있다. KRaft는 ZooKeeper의 역할을 Kafka 자체로 통합한 것이다.
kafka 클러스터는 여러 브로커로 구성되며 각 토픽은 여러 파티션으로 나뉜다. 또한 각 파티션은 특정 브로커에 저장된다.
예를 들어, topic 1과 topic 2는 두 개의 파티션으로 나뉘어 있고 각 각의 파티션은 리더와 팔로워의 역할을 수행한다.
Leader
: 데이터를 읽고 쓰는 역할을 담당한다.follower
: 리더의 데이터를 복제(replication)하여 백업 역할을 수행한다. 장애 발생 시 리더 역할을 대신할 수 있다. kafka1은 partition1의 리더, kafka2는 partition2의 리더 역할을 하고 있다.
Consumer
는 소비자로써 메세지를 소비하는 주체이다. 역시 Producer의 존재를 모른다.
Consumer Group
은 데이터를 읽는 단위이다. 하나의 파티션은 동일한 컨슈머 그룹 내의 오직 하나의 컨슈머에만 할당된다. 동일한 컨슈머 그룹에 여러 컨슈머가 존재할 경우, 파티션은 자동으로 분배된다. 컨슈머의 개수가 파티션의 개수를 초과하면 초과된 컨슈머는 아무것도 할당받지 않는다.
예를 들어, partition1은 consumer1에 partition2는 consumer2에 할당되어 소비된다.
Leader
는 특정 파티션의 읽기와 쓰기를 담당한다. 컨슈머와 프로듀서는 항상 리더 파티션과 통신하여 데이터를 읽고 쓴다. Replication Factor
를 설정하여 복제본의 갯수를 설정할 수 있다.
예를 들어, replication factor=2로 설정하면 각 파티션의 데이터가 두 개의 Kafka 브로커에 복제된다.
반면 Follower
는 리더 파티션의 데이터를 주기적으로 복제하고 읽기와 쓰기에는 관여하지 않는다. 리더가 장애가 발생한 경우, 최신 데이터로 리더와 동기화된 상태여야만 리더로 승격될 수 있다.
acks
옵션은 프로듀서가 브로커에 메세지를 전송한 후 요청 완료를 결정하는 옵션이다.
akcs=0
acks=1
akcs=all(-1)
min.insync.replicas
개수 이상의 복제본의 응답 확인을 기다린다. 최소 복제본(min.insync.replicas)을 충족하지 못하면 메시지가 거부되고 프로듀서는 오류를 수신한다. (kafka 3.0 이후로는 acks=all이 default이다.)min.insync.replicas
: 메세지가 성공적으로 기록되기 위해 필요한 최소 동기화된 복제본의 개수를 의미한다. 예를 들어, Replication Factor가 3일 때 min.insync.replicas=2로 설정하면 최소 2개의 복제본이 메시지를 저장해야 성공으로 간주된다.
컨슈머 그룹으로 이루어진 컨슈머들 중 일부 컨슈머에 장애가 발생하면, 장애가 발생한 컨슈머에 할당된 파티션은 장애가 발생하지 않은 컨슈머에 소유권이 넘어가고 이러한 과정을 리밸런싱
이라고 한다. 리밸런싱 동안 컨슈머가 파티션을 재할당받기 때문에 일시적으로 데이터 소비가 중단될 수 있다.
예를 들어, partition1을 소비하는 consumer1이 다운되면 컨슈머 그룹 내에서 리밸런싱이 일어나고 이를 통해 partition1은 consumer2에 할당되어 cosumer2는 partition1과 partition2를 소비하게 된다.
이런 과정이 일어나더라도 offset
정보를 활용하면 데이터를 중복이나 누락없이 저장할 수 있다.
offset
은 kafka의 파티션 내에서 각 메시지가 가지는 고유한 위치를 나타내는 번호이다. 컨슈머는 이 오프셋을 사용하여 자신이 마지막으로 처리한 메시지의 위치를 추적할 수 있다. 오프셋은 kafka의 내부 토픽 __consumer_offsets
에 저장된다.
예를 들어, consumer1이 partition1에서 메시지(offset 0~15)를 읽고 다운되면 리밸런싱이 발생된다. partition1은 consumer2에 재할당되고 consumer2는 partition1과 partition2를 모두 처리하게 된다. 또한 partition1의 마지막 커밋된 오프셋 정보를 확인하고 offset16부터 데이터를 읽기 시작한다.
자동커밋
은 특정 간격마다(기본값 5초) kafka가 컨슈머의 처리 상태를 기반으로 오프셋을 저장한다. 하지만 메시지가 처리되지 않았더라도 오프셋이 커밋될 수 있어 데이터 손실 위험이 있다. 수동커밋
은 메시지를 성공적으로 처리한 이후에만 오프셋을 커밋하도록 제어할 수 있다. auto.offset.reset
: 컨슈머가 처음 토픽에 연결되었을 때, 또는 이전에 커밋된 오프셋이 없을 때 어디에서부터 데이터를 읽을지 지정한다. earliest
와 latest
는 새 컨슈머 그룹이나 기존 오프셋이 없는 경우에만 적용되며 기존 오프셋이 있으면 항상 해당 위치에서부터 읽는다.earliest
: 가장 오래된 메시지부터 읽는다.latest
: 기본값으로 가장 최근 메시지부터 읽는다.none
: 이전 커밋된 오프셋이 없으면 오류가 발생한다. enable.auto.commit
: 자동 커밋 활성화 여부를 설정한다. auto.commit.interval.ms
: 자동 커밋 간격을 설정한다. 기본값은 5초이다. enable.auto.offset.store
: 오프셋 저장을 자동으로 할지 여부를 결정한다.