Kafka Cluster의 성능과 고려요소들
목차
[개요]
- Produce & Consume의 Request가 어떻게 처리되는지 알아야 한다.
- 비효율적인 Request가 Broker 성능에 어떤 영향을 줄지 가늠해보아야 한다.
- Broker의 내부 동작을 알고 있어야 한다.
- Controller 선출 방법
- Broker 장애감지 방법
- Controller 장애 후 복구 과정에서 파티션 수가 중요한 이유를 알아야 한다
[Kafka Cluster에 영향을 주는 요소들]
Client 설정들
- 주어진 처리량에 대해 최적화 되지 않은 클라이언트는 필요이상의 request를 생성한다.
- Kafka는 기본적으로 커넥션을 계속 사용하는 것을 고려해 놓았기 때문에 하나의 요청에 많은 데이터가 오는 방식이 더 적합하다.
- batch.size, linger.ms의 값을 적절히 설정
- max.fetch.wait 값을 적절히 설정
Controller 및 Zookeeper의 리더 선출 방식
Controller
컨트롤러는 다른 브로커들의 활성상태를 감시한다.
파티션 리더를 선출하는 역할도 하며 이 정보를 주키퍼에 저장한다.
- zookeeper.session.timeout.ms=18s
Broker
브로커는 셧다운 되면 컨트롤러에 알리며 브로커들도 컨트롤러가 잘 살아있는지 감시한다.
- replica.lag.time.max.mas=30s
- replica.fetch.min.bytes=1
- replica.fetch.wait.max.ms=500ms
Zookeeper
파티션 리더 및 컨트롤러가 변경되면 주키퍼가 병목지점이 될 수도 있다.
쓰기 작업이 발생하려면 주키퍼 쿼럼이 유지된 상태여야 한다.
앙상블에 노드가 많아질수록 더 지연시간이 커질 수 있다. (권장: 3,5,7. 그 이상은 굳이 필요없음)
- tickTime=2s (주키퍼 끼리 통신하는 것의 heartbeat)
- syncLimit=2 (min.isr과 비슷)
- fsync.warningthresholdms=1s
토픽 설정
파티션 수 결정
- 트래픽이 적은 토픽은 1개로 시작하여 부족한 경우 브로커 개수의 배수로 늘린다.
- 트래픽이 많은 토픽은 벤치마크 수행 후 결정한다.
- 내구성이 필요한지?
- 클러스터의 규모는?
- 처리량은 어느정도 되는지?
Replication Factor
- Replication Factor 설정을 통해 내구성을 올릴 수 있다.
- auto.create.topics.enable=true로 설정된 경우 default.replication.factor 값을 적절히 설정해주도록 한다.
- 너무 많이 잡을 경우 내구성은 오를 수 있지만 지연시간이 증가할 소지가 있다.
Replica Assignment
- 토픽 생성 시 결정된다.
- broker.rack이 있는 경우 broker.rack에 균등하게 알아서 분포된다.
- 수동배치가 필요한 경우 reassign-partitions 커맨드로 수동 배치 한다.
[Kafka Cluster의 목표별 고려요소들]
카프카를 사용할 때 크게 4가지로 구분하여 목적에 맞게 클러스터를 세팅하는 것이 좋다.
- Throughput: 처리량
- Latency: 지연시간
- Durability: 카프카에 들어온 메시지를 잃어버리지 않는 것.
- Availability: 무슨일이 있더라도 항상 서비스가 되어야 하는 것.
Throughput (처리량)
많은 데이터를 이동시키는 것.
간단하게 파티션을 증가시킴으로써 달성할 수 있다. 하지만 마냥 파티션을 늘리면 서버당 더 많은 파일처리가 동시에 필요해지고, 복구시에 한 번에 많은 파일에 접근해야하므로 성능에 악영향을 줄 수 있다.
클라이언트 입장에서도 더 많은 배치가 필요하기 때문에 메모리 요구사항이 늘어난다.
Producer
- batch.size=250000 (Default: 16384)
- linger.ms=100 (Default: 0)
- compress.type=lz4 (Default: none)
- acks=1 (내구성을 희생)
- buffer.memory=파티션 수에 따라 적절히 조절
Consumer
- fetch.min.bytes=1000000 (Default: 1. Fetch당 데이터크기 증가)
Latency (지연)
가능한 짧은 시간 안에 데이터를 전송할 때 중요시 하는 것.
시간에 민감한 비즈니스 처리 시 최우선 고려사항.
Confluent 블로그 참조: Tail Latency at Scale with Apache Kafka (confluent.io)
Producer
- linger.ms=0 ~ 5 (Default: 0)
- compression.type=none or lz4 (Default: none)
- acks=1
Consumer
- fetch.min.bytes=1 (Default: 1)
Broker
- num.replica.fetchers (Default: 1): 팔로워가 리더의 페이스를 따라가지 못하는 경우 늘려줌
Durability (내구성)
데이터 손실이 되면 안되는 상황에서 최우선 고려.
Replication Factor와 Min ISR 수치를 높여서 보장성을 높일 수 있다. 하지만 복제할 내용이 많아져서 성능상 하락이 있을 수 있음.
Broker
- Recplication.Factor>=3
- Min.ISR>=2
- log.flush.interval.ms / message: 브로커가 페이지 캐시에 있는걸 flush하는 주기
- 기본적으로 OS가 알아서 Page Cache에 있는 내용을 디스크로 주기적으로 써주는데, 이 주기를 직접 설정하여 갑자기 브로커가 내려갔을 때 손실이 일어나는 것을 방지
- 가급적이면 설정하지는 않고 OS에 맡기는 걸 추천한다고 한다.
Producer
- acks=all
- enable.idempotence=true (Default: false)
Consumer
- enable.auto.commit=false (Default: true)
Availability (가용성)
장애가 나도 계속 서비스가 가능한 것을 목표로 한다.
Broker
- min.ISR = 1
- num.recovery.threads.per.data.dir = recovery될 때 세그먼트에 있는 것을 page cache에 올려서 최대한 빨리 복구하려고 할 때.
- unclean.leader.election = true (Default: false). ISR목록에 없는 브로커를 리더로 선출하기 때문에 데이터 유실이 될 수 있다.
[권장사항]
- 성능의 초점은 가장 중요한 비즈니스의 요구사항에 맞춰 진행한다. (ex: 가용성 우선, TPS우선)
- 이러한 목표 하에서 여러 튜닝을 진행한다 (배치 크기 등등)
- 트래픽을 평가하고 파티션 수를 결정할 때는 향후 트래픽이 증가할 수 있음을 고려하고 선정한다.
- 메시지가 변경되거나하면 이를 고려하여 다시 성능 테스트를 하거나 수치를 점검한다.
- 모니터링도 수시로 항상 진행한다. 적절한 모니터링 환경이 클라이언트, 클러스터 양쪽에 모두 세팅되어 있어야 한다.