프로듀서
- 카프카에 필요한 데이터를 선언하고 브로커의 특정 토픽의 파티션에 전송
- 리더 파티션을 갖고 있는 카프카 브로커와 직접 통신
프로듀서 내부 구조
- ProducerRecord : 프로듀서에서 생성하는 레코드. 오프셋 미포함
- Partitioner : 어느 파티션으로 전송할지 지정하는 파티셔너
- 메시지 키에 따라 동작
- 메시지 키를 해시해 키가 동일하면 동일한 파티션으로 전송한다
- Accumulator : 배치로 묶어 전송할 데이터를 모으는 버퍼
- Sender : 브로커로 데이터 전송
파티셔너
- default : UniformStickyPartitioner
- 메시지 키가 있을 경우 동작
- 동일한 메시지 키가 존재하는 레코드는 동일한 파티션 번호에 전달됨
- 만약 파티션 개수가 변경될 경우 메시지 키와 파티션 번호 매칭이 깨지게 됨
- 처음부터 충분한 개수의 파티션을 확보해놔야 위 문제를 줄일 수 있다
- UniformStickyPartitioner와 RoundRobinPartitioner 둘 다 메시지 키가 있을 때는 메시지 키의 해시값과 파티션을 매칭하여 레코드 전송
- 메시지 키가 없을 경우 동작
- 메시지 키가 없을 때는 파티션에 최대한 동일하게 분배함
- UniformStickyPartitioner는 RoundRobinPartitioner의 단점을 개선한 버전
- RoundRobinPartitioner
- ProducerRecord가 들어오는 대로 파티션을 순회하면서 전송
- Accumulator에서 묶이는 정도가 적기 때문에 전송 성능이 낮음
- UniformStickyPartitioner
- Accumulator에서 레코드들이 배치로 묶일 때까지 기다렸다가 전송
- 배치로 묶일 뿐 결국 파티션을 순회하면서 보내기 때문에 모든 파티션에 분배되어 전송됨
- RoundRobinPartitioner에 비해 향상된 성능을 가짐
- 커스텀 파티셔너
- 메시지 키 뿐만 아니라 메시지 값까지 확인해서 특정 파티션으로 보내는 로직을 커스텀하게 구현해 쓸 수 있다
프로듀서 주요 옵션(필수)
- bootstrap.servers
- 프로듀서가 데이터를 전송할 대상 카프카 클러스터에 속한 브로커의 호스트 이름:포트를 1개 이상 작성
- 2개 이상 브로커 정보를 입력해 일부 브로커에 이슈가 발생하더라도 접속하는 데 이슈가 없도록 설정 가능
- key.serializer
- value.serializer
- 팁
- 웬만하면 String으로 직렬화한다
- 왜냐하면, kafka-console-consumer를 사용하면 String으로 역직렬화가 가능하기 때문
- 또한, 다양한 Consumer에서 가져가 역직렬화할 때, String으로 직렬화 기준을 통일하면 디스크/네트워크 용량 측면에서 손실은 있지만 운영상 이점이 있기 때문
프로듀서 주요 옵션(선택)
- acks
- 프로듀서가 전송한 데이터가 브로커들에 정상적으로 저장되었는지 전송 성공 여부를 확인하는 데 사용하는 옵션. 기본값은 1
- 전송만 성공했는지, 리더 파티션에만 저장되었는지, 팔로 파티션까지 복제가 되었는지 등 확인
- linger.ms
- 배치를 전송하기 전 까지 기다리는 최소 시간. 기본값은 0
- 일부 지연을 감수하고 최대한 많은 데이터를 한번에 보내고 싶으면 옵션 지정 가능
- retries
- 브로커로부터 에러를 받고 난 뒤 재전송을 시도하는 횟수. 기본값은 2147483647
- 재전송 필요없으면 값을 줄이거나 0으로 설정
- max.in.flight.requests.per.connection
- 한 번에 요청하는 최대 커넥션 개수. 설정된 값만큼 동시에 전달 요청을 수행
- sender에서 브로커로 데이터 전송 시 커넥션을 생성해서 진행하는데, 브로커로 동시에 전송할 양이 많다면 해당 설정값을 늘려 대응할 수 있음
- partitioner.class
- 레코드를 파티션에 전송할 때 적용하는 파티셔너 클래스
- 2.5.0부터는 UniformStickyPartitioner가 기본값
- enable.idempotence
- 멱등성 프로듀서로 동작할지 여부
- 데이터 중복 전송을 막기 위함
- transactional.id
- 프로듀서가 레코드를 전송할 때 레코드를 트랜잭션 단위로 묶을지 여부를 설정
- 기본값은 null
ISR(In-Sync-replicas)
- ISR : 리더 파티션과 팔로 파티션이 모두 싱크 된 상태
- ISR이라는 용어가 나온 이유는 팔로 파티션이 리더 파티션으로부터 데이터를 복제 하는데 시간이 걸리기 떄문
- 이 복제 시간 차 때문에 리더와 팔로 간 오프셋 차이가 발생함
acks
- acks 옵션을 통해 카프카 클러스터에 얼마나 신뢰성 높게 저장할지 지정할 수 있다
- 신뢰성과 성능은 trade-off 관계
acks=0
- 프로듀서가 리더 파티션으로 데이터를 전송했을 때 리더 파티션으로 데이터가 저장되었는지 확인하지 않는다는 뜻
- 리더 파티션은 데이터가 저장된 후에 데이터가 몇번째 오프셋에 저장되었는지 리턴하는데
- acks가 0으로 설정되어 있으면 저장 여부에 대한 응답을 받지 않는다
- 데이터 전송 속도는 1 또는 all보다 훨씬 빠르다
- 데이터 일부 유실 발생해도 속도가 중요한 경우에는 이 옵션값 사용하면 됨
acks=1
- 프로듀서는 보낸 데이터가 리더 파티션에만 정상 적재되었는지 확인함
- 리더 파티션에 정상 적재되지 않았다면, 적재될때까지 재시도 가능
- 리더 파티션에 적재되었음을 보장해도 데이터는 유실될 수 있다
- 복제 개수를 2 이상으로 운영할 경우 리더에 적재 완료되어도 팔로에는 아직 동기화되지 않을 수 있는데, 팔로에서 데이터를 복제하기전에 리더에 장애가 발생하면 동기화되지 못한 데이터는 유실될 수 있기 때문
acks=-1(all)
- 프로듀서는 보낸 데이터가 리더 파티션과 팔로워 파티션에 모두 정상 적재되었는지 확인함
- 일부 브로커에 장애가 발생해도 안전히 데이터를 전송하고 저장할 수 있음을 보장할 수 있다
- 대량 처리시 속도가 너무 느려 처리량이 안좋음
- min.insync.replicas 옵션값에 따라 팔로워 파티션을 몇개까지 검증할지 정해지고, 안정성이 달라짐(ISR 중 몇개의 파티션에 데이터가 적재되었는지)
- 2로 설정해 1개의 팔로 파티션만 확인해도 충분
- 모든 서버가 동시에 장애가 날 확률이 잘 없기 때문
출처 : 인프런 - [아파치 카프카 애플리케이션 프로그래밍] 개념부터 컨슈머, 프로듀서, 커넥트, 스트림즈까지!