Search

카프카 핵심 가이드 ch.2

카프카 설치 및 구성 옵션 톺아보기

핵심 구성 옵션

1. broker.id
모든 카프카 브로커가 가져야하는 식별자값
기본값은 0이지만 어떤 값도 가능
하나의 카프카 클러스터 내에서는 고유한 값이어야한다.
번호는 임의 선택 가능. 유지보수 작업중에 브로커 간에 숫자 바꾸는 것도 가능. 그러나 숫자 바꾸는건 권장하지 않음.
2. listeners
카프카의 실행에 사용되는 tcp 포트
기본값은 9092
- 어떤 포트번호로도 설정가능하지만 1024보다 작은 값으로 설정한다면 카프카가 root 권한으로 시작되어야하기에 바람직하지 않다.
3. zookeeper.connect
브로커의 메타데이터를 저장하기 위한 주키퍼의 위치
기본값은 localhost:2181/
[호스트이름:포트/경로] 의 형식으로 입력하면 된다.
여기서 경로는 일반적으로 chroot 경로를 사용한다.
다른 애플리케이션들과 충돌하지 않고 주키퍼 앙상블을 공유해서 사용
4. log.dirs
카프카는 모든 메시지를 로그 세그먼트 단위로 파일에 모아서 디스크 디렉토리에 저장한다.
여러 경로를 쉼표로 구분하여 지정가능
두개이상의 경로가 지정되면 해당 브로커가 모든 경로에 파티션을 저장한다.
사용빈도가 가장 적은 데이터를 교체하는 방식으로 한 파티션의 모든 로그 세그먼트를 같은 경로에 저장.
브로커가 새로운 파티션을 저장할때는 가장 적은 디스크 용량을 사용하는 경로가 아닌, 가장 적은 수의 파티션을 저장한 경로를 사용한다.
5. num.recovery.threads.per.data.dir
카프카는 스레드 풀을 사용해서 로그 세그먼트를 처리한다.
[ 스레드 풀을 사용하는 경우 ]
1) 브로커가 정상적으로 시작될때 : 각 파티션의 로그 세그먼트 파일을 열기 위해 사용
2) 장애 발생이후 다시 시작될 때 : 각 파티션의 로그 세그먼트를 검사하고 불필요한 부분을 삭제하기 위해 사용
3) 종료될때 : 로그 세그먼트 파일을 정상적으로 닫기 위해 사용
기본적으로 로그 디렉토리당 하나의 스레드만 사용한다.
스레드들은 브로커의 시작과 종료 시에만 사용되기 때문에 병행처리를 하도록 가능한 많은 수의 스레드를 설정하는 것이 좋다.
설정 값의 의미 : log.dirs 별 쓰레드 수
num.recovery.threads.per.data.dir = 8, log.dirs = 3 ⇒ 전체 스레드 수: 24
6. auto.create.topics.enable
기본값은 true
다음의 경우, 브로커는 자동으로 토픽을 생성한다.
1) 프로듀서가 토픽에 메시지를 쓸때
2) 컨슈머가 토픽의 메시지를 읽기 시작할때
3) 클라이언트에서 토픽의 메타데이터를 요청할때
7.
auto.leader.rebalance.enable
리더 역활이 여러 브로커에 균등하게 분산되도록 함 (false)
전체 파티션 중 특정 브로커에 리더 역활이 할당된 파티션 비율이 leader.imbalance.per.broker.percentage에 설정된 값을 넘어가게 되면 리밸런싱 일어남
8.
delete.topic.enable
클러스터의 토픽을 임의로 삭제하지 못하게 막음

토픽 기본설정

1. per.topic 매개변수 사용 (kafka 2.0)
토픽당 로그 보유시간, 토픽당 로그 보유 바이트, 토픽당 로그 보유 세그먼트 등을 토픽에 지정 가능.
그러나 지금은 그렇게 할 수 없으며, 관리도구를 사용해야한다.
2. num.partitions
새로운 토픽이 몇개의 파티션으로 생성되는지를 지정 (기본값 = 1)
자동 토픽생성이 활성화 될때(auto.create.topics.enable=true) 사용된다.
파티션은 증가시킬수 있지만 감소시킬 수는 없다
토픽의 크기가 확장되는 방법이 파티션 ⇒ 브로커가 추가될 때 클러스터 전체에 걸쳐 메시지가 고르게 저장되도록 파티션 개수를 설정하는 것이 중요하다.
클러스터의 브로커수와 같게 하거나 배수로 토픽의 파티션 개수를 설정한다. ⇒ 브로커마다 파티션이 고르게 분산될 수 있고, 저장메시지도 고르게 분산될것이다.
[ 파티션 개수 산정시 고려할점 ]
1) 단위 시간당 토픽의 데이터 처리량은? 
예를 들어, 초당 100KB 또는 1GB를 예상하는가?
2) 한 파티션의 데이터를 읽을때 목표로 하는 최대 처리량은?
파티션 하나는 항상 한 컨슈머가 소비한다.
3) 하나의 파티션에 데이터를 생성하는 프로듀서당 최대 처리량도 컨슈머와 같은 방법으로 산정할 수 있다. 그러나 대개 프로듀서는 컨슈머보다 훨씬 빠르게 처리되므로 처리량을 조사하지 않아도 무방하다.
4) 키를 사용해서 파티션에 메시지를 쓰는 경우에는 향후에 파티션을 추가할때 개수 산정이 어려울 수 있다. 
따라서 현재보다는 향후에 예상되는 사용방법을 기준으로 처리량을 추산하자.
5) 브로커마다 파티션 개수와 디스크 용량및 네트워크 처리속도를 고려하자.
6) 파티션 개수를 너무 많이 고려하지 말자. 
왜냐하면 각 파티션은 브로커의 메모리와 그 외 다른 자원을 사용하므로 리더 선정에 더 많은 시간이 소요되기 때문.
7) 위 모든 것을 고려해 파티션 개수를 너무많이 산정하지 말자. 초당 1Gb로 토픽을 읽고 쓰기 원하는데 각 컨슈머가 초당 50MB만 처리할수 있다면 (DB 쓰기관련 이슈로 인해) 최소한 20개(1000/50) 의 파티션이 필요하다. 자세한 정보가 없다면 파티션 크기를 하루에 6GB미만으로 제한할것을 권한다. (왜?)
⇒ 결론 : 파티션 개수 나중에 바꾸려면 생각해야될게 많을 수 있으니까 처음 정할때 잘 정해야 되는데 더도 덜도 말고 컨슈머가 견딜만한 정도의 양이 한 파티션에 배정될 정도의 개수로 나눌것!
참고. kafka 브로커, topic, partition, segment 구조
1.
Producer는 kafka의 A라는 Topic으로 메시지를 전달합니다.
2.
A Topic은 partition이 하나여서 0이며 Producer로부터 받은 메시지를 Partition의 Segment log파일에 저장합니다
3.
Broker의 Segment log file에 저장된 메시지는 Consumer가 읽어 갈 수 있습니다.
4.
Consumer는 A Topic을 컨슘 해서 해당 토픽 내 파티션 0의 segment log file에서 메시지를 가져옵니다.
Producer에 의해서 브로커로 전송된 메시지는 토픽의 파티션에 저장되며, 각 메시지들은 세그먼트라는 로그 파일의 형태로 브로커의 로컬 디스크에 저장됩니다.
(카프카의 브로커 > 토픽 > 파티션 > 세그먼트(세그먼트 로그 파일)에 저장을 합니다)
위 내용이 숙지가 되었다면 아래를 이해할 수 있습니다.
3. log.retention.ms
메시지 보존 기간 설정
보통 log.retention.hours로 설정하는데 이 경우, log.retention.ms 나 log.retion.minutes를 적게되면 그 값으로 오버라이딩 되니까 그냥 log.retention.ms를 쓰는 것을 권장함
4. log.retention.bytes
저장된 메시지들의 전체 크기를 기준으로 만기 처리
이 값은 모든 파티션에 적용된다.
log.retention.ms , log.retention.bytes 둘다 설정할 경우 둘중 하나의 조건이 충족될 때 메시지가 삭제된다.
5. log.segement.bytes
앞의 메시지 보존설정은 개별 메시지가 아닌 로그 세그먼트 파일을 대상으로 처리된다.
참고로 세그먼트가 작성이 완료될 때까지, 메세지는 커밋이 되거나 삭제가 되지 못한다.
즉 처리되지 못한 메세지도 세그먼트 작성 중이라면 삭제가 되거나 버려지지 않음
메시지가 카프카 브로커에 생성될 때는 해당 파티션의 로그 세그먼트 파일끝에 추가된다.
로그 세그먼트에는 메시지의 내용만 저장되는 것이 아니라 메시지의 key, value, offset, message size와 같은 정보가 함께 저장됩니다.
하나의 로그 세그먼트 크기가 너무 커지면 파일 관리가 어렵기 때문에 최대 크기는 1GB 기본값으로 설정되어 있습니다.
해당 설정 값은 log.segment.bytes 매개변수에 지정된 크기 (기본값은 1GB)가 되면 해당 로그 세그먼트 파일이 닫히고 새로운 것이 생성되어 열리게 됩니다.
그리고 닫힌 로그 세그먼트 파일은 만기가 된 것으로 간주한다. 따라서 로그 세그먼트의 크기를 더 작은 값으로 지정하면 더 빈번하게 파일이 닫히고 새로 생성되므로 전반적인 디스크 쓰기 효율이 감소된다.
1GB보다 크기가 커진다면?
Rolling 전략을 사용
ex) 하나의 로그 세그먼트에 계속 메시지를 덧붙이다가 1GB에 도달하면 close한뒤 새로운 로그 세그먼트를 생성하는 방식
1GB 크기의 로그 세그먼트 파일이 무한히 늘어날 경우를 대비해 관리 계획을 수립해야 합니다.
관리 계획은 크게 로그 세그먼트 삭제와 컴팩션으로 구분할 수 있습니다.
만일 토픽의 데이터 저장률이 낮다면 로그 세그먼트의 크기를 조정하는 것이 중요하다.
하루에 100MB의 메시지만 토픽에 수록되고 log.segment.bytes의 값이 기본값으로 1GB인 경우, 하나의 로그 세그먼트를 채우는데 10일이 소요된다.
그러나 로그 세그먼트 파일은 닫혀야만 만기가 될 수 있으므로 만일 log.retention.ms가 1주일로 설정되어 있다면 로그 세그먼트에 저장된 메시지들은 17일동안 보존될 것
 왜냐하면 마지막 메시지를 스면서 로그 세그먼트 파일이 닫히는데 10일이 소요되고, 다시 보존기간인 7일이 지나야 만기가 되기 때문
특정 타임스탬프 시간으로 파티션의 오프셋을 요청할 수 있는데 이경우에도 log.segment.bytes가 관여된다.
특정 시간에 해당하는 로그 세그먼트 파일을 찾기 때문. 지정된 타임스탬프 이전에 생성되고 마지막 수정시간이 해당 타임스탬프 이후인 로그 세그먼트 파일을 찾는다.
그리고 찾은 로그 세그먼트파일의 시작 오프셋과 파일 이름을 반환한다.
6. log.segment.ms
지정된 시간이 되면 로그 세그먼트 파일을 닫는다. 위의 log.segment.bytes 와 대응된다.
기본적으로 이 속성은 설정되있지 않기때문에 로그 세그먼트 크기 제한으로만 닫히게 된다.
디스크 성능이 좋지 않다면 이 속성은 피하자.
왜? 다수의 로그 세그먼트가 동시에 닫히는 것에 의해 디스크 성능에 영향을 끼칠 수 있기 때문.
7. message.max.bytes
브로커가 감당할 수 있는 하나의 메세지의 최대크기.
기본값은 1000000 (1mb)
프로듀서가 이 값보다 큰 메시지를 보내는 경우 프로듀서에 에러를 날린다. 당연히 컨슈머에도 이 값보다 큰 메세지를 보내지는 않는다.
만약 압축을 풀어서 보내려는데 이 값보다 커진다면 압축해서 보내야 합니다..!
기본값이 클수록 네트워크 비용, 요청당 작업시간, 처리량 문제가 생기기 때문에 성능 튜닝시 고려할 요소중 하나다.