-
카프카 기본 구조
- Topic
- Topic은 Partition으로 구성된 일련의 로그 파일
- RDBMS의 테이블과 유사한 기능
- Key, Value 기반의 메시지 구조
- Value는 어떤 타입도 가능함(문자열, 숫자, 객체, Json, Avro, Protobuf 등)
- 로그 파일처럼 연속적으로 추가되는 데이터를 저장하는 구조(시간 흐름 데이터) → update의 개념이 존재하지 않음
- 1개 이상의 partition을 가지며 병렬 성능과 가용성 기능의 핵심 요소, 메시지는 이를 고려해 개별 파티션에 분산 저장됨(RR:Round Robin 방식)
- Partition
-
개별 파티션은 정렬되고, 변경할 수 없는 일련의 레코드로 구성된 로그 메시지
-
개별 레코드는 offset으로 불리는 일련 번호를 할당
-
개별 파티션을 다른 파티션과 완전히 독립적인 형태
-
개별 파티션내에 정렬되고 offset이 파티션별로 할당되고 참조
-
토픽과 파티션의 병렬 처리 과정
- 위처럼 노드병렬처리를 효과적으로 하기 위해 복제 파티션 사용
- 특정 노드가 다운되더라도 기능상으로는 문제를 가지지 않게 됨
- Leader는 원본 파티션, Follower는 복제 파티션
- 위처럼 교차해서 복제를 관리하면 특정 노드(브로커)에 종속적으로 작동하지 않도록 할 수 있음
- 하지만 저장소의 사용이 증가하게 됨
-
Topic 생성 및 정보 확인하기
- 카프카 커맨드
--bootstrap-server
- Topic을 생성할 kafka Broker 서버 주소 : 포트
- 예)
--bootstrap-server localhost:9092
--create
--topic <토픽이름>
: 지정된 토픽이름으로 토픽 생성
--partitions <파티션 개수>
: 지정된 개수만큼 파티션 생성
--replication-factor <복제본 개수>
: 지정된 개수만큼 복제본 생성(원본 개수 포함 개수)
--list
: 브로커에 있는 토픽 목록
--describe
--topic <토픽이름>
: 지정된 토픽이름의 세부 정보를 표시
-
Producer, Consumer 개요
첫번째 이미지는 간단한 구조, 두번째 이미지는 보다 상세하게 표현한 구조 이미지
- Producer
- 카프카에 메세지를 보냄(메세지 write)
- 성능/로드밸런싱/가용성/업무 정합성등을 고려하여 어떤 브로커의 파티션으로 메세지를 보낼 지 결정
- 즉, 동적으로 메세지를 보낼 브로커를 결정
- ProducerRecord
- Producer가 보낼 때 사용하는 객체
- Topic, Partition, Key, Value, Header로 구성됨
- Consumer
- Topic에서 메세지를 읽어 들임
- 여려 개의 Consumer로 구성된 경우, 어떤 브로커의 파티션에서 메세지를 읽어들일지 전략적으로 결정
auto.offset.reset
- Consumer가 Topic에 처음 접속하여 Message를 가져올 때 처음 offset부터 가져올 것인지, 마지막 offset부터 가져올 것인지 설정하는 파라미터
- ealiest: 처음 offset부터 읽음
- latest: 마지막 offset부터 읽음(애매한 부분인데, 현재 offset이 7까지일 경우, 8 offset부터 읽도록하여 현재 카프카의 메세지를 읽지 않는 것이 핵심
- 파티셔너: 파티셔너
-
Serializer(직렬화)
- 자바 객체의 Serialization
- 객체를 객체의 유형, 데이터의 포맷, 적용 시스템에 상관없이 이동/저장/복원을 자유롭게 하기 위해서 바이트 배열(바이트 스트림)형대로 저장하는 것
- 객체는 Serializtion, Desirializtion을 통해 System to System 또는 서로 다른 저장영역에 이동/저장/복원을 자유롭게 진행
- 과정: Serilalization을 통해 객체가 바이트 스트림으로 변환되어 네트웍을 통해 손쉽게 데이터를 전송할 수 있으며 Desirialization을 통해 바이트 스트림은 다시 원본 객체로 변환되어 자유로운 객체 데이터 이동 수행
-
Key값을 가지는 메세지의 전송
- 중요한 것은 Key는 메세지를 구분한기 위한 고유키가 아님을 알아야함
- 기본적으로 카프카에 전송하기 전
send()
메서드에서 Partitioner를 통해 파티션 전략이나 특정 파티션을 결정
- 메세지는 Producer를 통해 전송시 Partitioner을 통해 토픽의 어떤 파티션으로 전송되어야할 지 미리 결정이 됨
- Key값을 가지지 않는 경우 라운드 로빈(Roud Robin), **스티키 파티션(Sticky Partition)**등의 파티션 전략들이 선택되어 파티션 별로 메시지가 전송될 수 있음
- 위와 같은 전략들로 카프카에 전송했을 때 Producer에서 보낸 순서를 보장하지 않게 되는데 카프카와 같은 분산 시스템에서는 당연한 결과
- 만약 전송순서를 보장하기 위해서는 단일 파티션으로 작동하도록 하면 가능하지만, 분산 시스템에서 병렬로 처리해서 얻는 이점들이 사라짐
-
여러 개의 파티션을 가지는 메시지에 키를 함께 전송
- key값을 통해 카프카로 전송할 때 key값과 partitions 번호랑은 무관함
- key가 있다면 key값을 해싱하고 해싱 결과를 이용하여 파티션 선정
- key값이 같은 경우에는 같은 partition으로 들어가도록 되어 있음
-
여러 개의 파티션을 가지는 메시지에 Key없이 전송하는 경우
- 파티션 분배 전략
-
라운드 로빈(2.4버전 이전의 방식)
- 최대한 파티션에 균일하게 메세지를 보내는 전략
- 메시지 배치를 순차적으로 다른 파티션으로 전송함
- 메시지가 배치 데이터를 빨리 채우지 못하면서 전송이 늦어지거나 배치를 다 채우지 못하고 전송하면서 전송 성능이 떨어지는 문제 발생
-
스티키 파티셔닝(2.4버전 이후의 방식)
- 라운드 로빈의 성능을 개선하고자 특정 파티션으로 전송되는 하나의 배치에 메세지를 빠르게 먼저 채워서 보내는 방식
- 각 배치별로 끊어서 읽어오기 때문에 순서를 보장할 순 없음
-
Consumer Group과 Consumer 이해
-
모든 Consumer들은 단 하나의 Consumer Group에 소속되어야 하며, Consumer Group은 1개 이상의 Consumer를 가질 수 있음
-
파티션의 레코드들은 단 하나의 Consumer에만 할당
-
Consumer Group에 Consumer가 1개만 있는 경우
-
Consumer Group 내에 2개의 Consumer가 있지만 토픽 파티션의 개수보다 적은 경우
- 리밸런싱
- Consumer Group내에 Consumer 개수 등의 변화가 있을 때 마다 파티션과 Consumer의 조합을 변경하는 Rebalancing 발생
- Consumer Group내에 Consumer 개수가 변경되면 각 할당하는 파티션의 개수가 달라지는데 이때 발생
- 만약 파티션이 4개이고 Consumer Group에 Consumer가 4개에서 5개가 되는 경우에도 rebalancing이 발생함
- 위 경우 남는 컨슈머와 할당된 컨슈머가 번갈아가면서 작동하지는 않음(한 번 할당된 파티션은 리밸런싱 전까지는 바뀌지 않음)
-
Consumer Group이 2개인 경우
-
kafka-consumer-groups 명령어로 Consumer Group과 Consumer, Lag 확인
- kafka-consumer-groups 명령어로 할 수 있는 것들
- Consumer Group List 정보
- Consumer Group과 Consumer 관계 및 구독하는 partition 정보(중요한 정보)
- Consumer Group 삭제(Consumer Group에 컨슈머가 하나도 없더라도 Consumer Group은 삭제되지 않음, 일정기간 유지됨, 하나의 컨슈머라도 남은 경우 삭제되지 않음)
- Producer가 전송한 Log Message의 지연 및 Lag 정보
-
Kafka Config 구분
-
Broker와 Topic 레벨 Config
- kafka 서버에서 설정되는 Config
- Topic의 Config값은 Broker레벨에서 지정한 Config를 기본으로 설정하여 별도의 Topic 레벨 Config를 설정할 경우 이를 따름
- 보통 server.properties에 있는 Config는 변경시 Broker 재가동이 필요한 static config이며, Dynamic Config는 kafka-configs를 이용하여 동적으로 config 변경 가능
-
Producer와 Consumer 레벨 Config
- kafka 클라이언트에서 설정되는 Config
- Client 레벨에서 설정되므로 server.properties에 존재하지 않고, kafka-configs로 수정할 수 없으며 client 수행시마다 설정할 수 있음
-
kafka-configs 사용
-
kafka-dump-log명령어로 로그 파일의 메세지 내용 확인
- 특정 파일을 넘겨주면 해당 파일의 로그를 확인
- 해당 로그 파일을 확인하여 특정 파티션에 어떤 메세지를 전송했는지에 대한 정보를 확인 가능
- .log형식으로 저장된 로그 파일을 읽어와서 iterator를 이용해 읽을 수 있음