Apache Kafak의 성능이 특정환경(데이터 유실일 발생하지 않고, 데이터 전송순서를 반드시 보장)에서 어느정도 제공하는지 확인하기 위한 테스트 결과 공유
데이터 전송순서를 보장하기 위해서는 Apache Kafka cluster로 partition을 분산할 수 없게되므로, 성능향상을 위한 장점을 사용하지 못하게 된다.
이번 테스트에서는 Apache Kafka의 단위 성능, 즉 partition 1개에 대한 성능만을 측정하게 된다.
향후, partition을 증가할 경우 본 테스트의 1개 partition 단위 성능을 기준으로 예측이 가능할 것 같다.
2. 2
우리가 원하는 Apache Kafka의 역할은?
데이터 전송순서를 유지하면서, 절대로 데이터를 유실하면 안된다!
데이터 전송순서를 유지하려면? 데이터 유실을 방지하려면?
• 반드시 전송이 성공 한 후에 다음 데이터 전송 à sync 방식
• Topic을 분산하면 안됨 à partition 1개
• Topic 당 1개의 Producer만 할당
• 복사본을 최대한 증가 à replica 3개
• 모든 복사본까지 저장된 후 다음 메시지 처리 à acks = -1
Throughput 최대화 Durability 보장
3. 3
요구하는 환경을 위한 Apache Kafka 설정은?
순서보장을 위한 producer 설정과, 유실방지를 위한 broker 설정 변경
Producer 설정 Apache Kafka 설정
• 데이터 전송 순서 보장
• Sync 방식 전송 (thread 1개)
• 데이터 유실 방지
• Acks : -1 (모든 복제본 저장 후, 다음 메시지 전송)
• Retris : 최대한 많은 재시도 (메시지 유실 없도록)
• 처리량 향상
• Compression : 압축알고리즘 최적화 (gzip, lz4, snappy)
• batch_size : 1회 전송에 보내는 size
• Topic 생성시 설정
• replication-factor : 3 (원본 포함 3개)
• partitions : 1 (데이터가 분산되지 않도록 설정, 순서보장)
• Kafka Broker 설정
• min.insync.replicas : 2
• 최소 2개의 복사본 있어야, 서비스 가능
• 가용성을 높이려면 1로 설정
• 데이터 유실을 최소화 하려면 높게 설정
4. 4
테스트 환경을 구성하자
Kafka Cluster로 데이터를 전송 및 수신하고, 성능지표를 수집하여 모니터링
• Topic은 partition 1로 구성하여 2번 Broker만 생성하도록 설정
• 나머지 broker는 replication을 위한 용도로 활용
• 3대 서버
• CPU : Dual Intel Xeon E5-2650 v4 (24 Cores, 2.20 GHz)
• MEM : 64 GB
• DISK : 2 TB, MegaRAID SAS 9361-8i, 12Gb/s
• Node 1
• Kafka Broker1, Zookeeper1
• Producer
• ELK Stack (logstash, kibana, elasticsearch)
• Node 2 (Topic 생성)
• Kafka Broker2, Zookeeper2
• Node 3
• Kafka Broker3, Zookeeper3
• Consumer
Producer
(filebeat)
테스트 환경 구성 테스트 서버 스펙
Kafka Cluster
Consumer
(logstash)
Monitoring
(ELK Stack)
JMX Metric 수집
Broker 1
Broker 2
Broker 3
• Message Size : 3 KB (3,000 byte)
• Apache Kafka 0.11.0
5. 5
[성능비교 1] 1개 Producer로 전송 (acks=1 vs acks=-1)
원본만 저장하는 방식이 1,000건 빠른걸 보면, 복제본에 많은 시간이 소요되지 않음
원본만 저장후 처리하는 방식(acks 1) vs 모든 복제본 저장후 처리 방식(acks -1)
(100만건 데이터를 전송후 평균처리속도 계산)
측정 항목 측정 값
(acks = -1)
측정 값
(acks = 1)
비고
처리 건수 4,600 건 / sec 5,600 건 / sec - 평균 초당 처리 건수
처리 용량 90 KB / sec 100 KB / sec - 기본 압축 (gzip) 적용
전송 파일 비교(건수) 동일 동일 - Consumer에서 수신한 파일과 동일
전송 파일 비교(순서) 동일 동일
- Consumer에서 수신한 파일과 동일
- Diff Command 로 확인
자원 사용량 (CPU) 평균 1 core 평균 1 core
자원 사용량 (Memory) 200 ~ 700 MB 200 ~ 700 MB - Heap Memory 2G 이하로 설정
6. 6
[성능비교 2] Producer 개수를 증가 (4, 10 개)
Producer를 증가시키면 처리성능도 함께 증가함 (4,600 à 29,000건)
(100만건 데이터를 전송 후 평균처리속도 계산)
측정 항목 측정 값
(acks = -1, producer = 4)
측정 값
(acks = -1, producer = 10)
비고
처리 건수 38,000 건 / sec 58,000 건 / sec - 평균 초당 처리 건수
처리 용량 280 KB / sec 370 KB / sec - gzip 알고리즘 적용
전송 파일 비교(건수) 동일 동일 - Consumer에서 수신한 파일과 동일
전송 파일 비교(순서) 동일 동일
- Consumer에서 수신한 파일과 동일
- Diff Command 로 확인
자원 사용량 (CPU) 평균 3 core 평균 3 core
자원 사용량 (Memory) 200 ~ 700 MB 200 ~ 700 MB
- CPU 사용률이 증가하는 것을 볼 때, Kafka Broker가 더 많은 메시지를 처리가능
- 즉, Producer가 모든 복제본이 완료되기까지 대기하는 시간으로 인하여, 많은 데이터를 전송하지 못함.
7. 7
[성능비교 3] 압축 알고리즘 변경 (gzip, snappy, lz4)
압축성능 및 처리성능 관점에서 lz4가 가장 효과적임
(100만건 데이터를 전송 후 평균처리속도 계산)
- 처리 성능만을 고려한다면, lz4 또는 snappy 알고리즘을 선택해야 하지만,
- Snappy 알고리즘은 압축률이 좋지 않아, lz4를 사용하는 것이 효과적
측정 항목 측정 값
(compression = lz4)
측정 값
(compression = snappy)
측정 값
(compression = gzip)
측정 값
(compression = none)
비고
처리 건수 88,000 건 / sec 90,000 건 / sec 57,000 건 / sec 33,000 건 / sec - 처리량은 lz4, snappy 가 높음
처리 용량 1,790 KB / sec 12,432 KB / sec 622 KB / sec 96,593 KB / sec - 압축률은 gzip이 가장 높음
전송 파일 비교(건수) 동일 동일 동일 동일
전송 파일 비교(순서) 동일 동일 동일 동일
자원 사용량 (CPU) 평균 0.7 core 평균 1.2 core 평균 1 core 평균 1.3 core
- Lz4가 cpu 사용률이 가장 낮음
- 압축을 하지 않은 경우, 더 많은
cpu time을 소요함.
자원 사용량 (Memory) 200 ~ 700 MB 200 ~ 700 MB 200 ~ 700 MB 200 ~ 700 MB
8. 8
[성능비교 3] 압축 알고리즘 변경 (gzip, snappy, lz4)
처리성능이 높으면서 CPU 사용량이 가장 적은 것이 lz4 압축
LZ4 snappy gzip 압축없음
[초당 처리 건수]
LZ4 snappy gzip 압축없음
[초당 데이터 처리량]
[CPU 사용량]
snappy gzip 압축없음LZ4
9. 9
테스트에서 사용한 Apache kafka 설정
구분 설정 파라미터 (Default) 내용 비고
Broker
replication.factor
(1)
- Topic 의 유실 방지를 위해 원본을 포함한 복제본 개수 (1 이상)
- 많은 경우 유실방지
- 적은 경우 성능향상
min.insync.replicas
(1)
- Broker 서버의 장애를 허용하는 최소 서버 개수
- 2인 경우 2대 까지는 서비스 가능 (1대만 남은 경수 서비스 불가)
- 많은 경우 데이터 유실방지
- 적은 경우 가용성 향상
message.max.bytes
(1,000,000)
- 한번의 요청 batch에서 전송 가능한 최대 bytes
- Message가 큰 경우(이미지 binary 등)
값을 증가
unclean.leader.election.enable
(false)
- 정상적으로 원본을 복제하지 못한 broker가 서비스를 할 수 있는지 여부
- True : 가능 (유실 가능)
- False : 불가(가용성 저하)
Producer
acks
(1)
- 0 : 원본 저장 확인 없이 응답
- 1 : 원본 저장 확인 후 응답
- -1 : 복제본 저장 완료 후 응답(가장 느림)
- 데이터 유실방지를 위해 -1 옵션 사용
max_retries
(3)
- 데이터 전송 실패시 재전송 회수
- 네트워크 및 시스템이 불안전한
환경에서는 높게 설정
batch.size
(16,384)
- 한번에 전송할 데이터의 크기 (byte)
- 테스트를 위해 사용한 Filebeat에서는 bulk_max_size를 이용하여 한번에 전송할 메시지 건수로 지정
- 많은 경우 전송효율 높음
- 적을 경우 전송효율 낮음
compression.type
(Gzip)
- 전송할 데이터를 압출할 알고리즘 지정 (gzip, lz4, snappy, none) - Lz4 알고리즘이 효율적
Consumer
enable_auto_commit
(true)
- 데이터를 수신한 뒤 자동으로 Commit할 것인지 지정
- 유실방지 위해 False로 설정하고, Biz
로직 동작후 직접 commit
auto_commit_interval_ms
(5,000)
- Auto commit이 true인 경우, commit할 주기를 지정
- 많은 경우 처리 성능 높음
- 적은 경우 처리성능 낮음
max.partition.fetch.bytes
(1,000,000)
- Broker의 message.max.bytes 설정이 변경될 경우, 최대 batch size를 가져올 수 있도록 함께 변경
10. 10
Apache Kafka 성능 개선을 위한 하드웨어 고려사항
고려사항 주요 설명
CPU CORE
• 처리량이 CPU에 많은 영향을 받지는 않지만, multi core를 권장
• 병행처리를 위해서는 빠른 core보다는 많은 core를 권장
Memory
• CPU보다는 MEMORY가 성능에 미치는 영향이 더 크다.
• 왜냐하면, 많은 데이터가 서버로 유입되고 관리되면서 발생하는 데이터를 page cache를 이용
하여 처리하기 위함.
DISK
• DISK의 처리성능이 중요함. (SATA 7200 rpm 기준)
• 병렬 Disk I/O를 위해 Disk의 개수가 많은 것이 좋음
• http://docs.confluent.io/1.0.1/kafka/deployment.html
OS 설정
• file descriptors 의 개수를 사전에 충분히 증가시켜야 함 (Topic의 수가 많아지고,
connection하는 producer, consumer가 증가할 경우)
• socket buffer size를 최대화 하여, 한번에 처리할 수 있는 처리량을 증가시킨다.
• OS 최적화 : https://kafka.apache.org/documentation.html#hwandos 참고
11. 11
테스트 결과 정리
초당 처리 건수는 Topic당 최대 90,00건을 처리하며, 유실없이 데이터 순서보장
초당 90,000 건 이상
(1개 Topic, 10개 producer 동시전송)
데이터 유실없이, 전송순서 보장
[ 고려사항 ]
• 전체 처리량 = 90,000건 * TOPIC 수
• Producer용 서버의 자원을 추가하면, 더 많은 데이터
처리 가능
• 압축 알고리즘 선택에 따라서 성능 및 전송효율 향상 가
능 (lz4 권장)
[ 고려사항 ]
• Network 장애로 인하여 특정 상황에서 데이터 중복 가
능 (유실 없음)
• 중복 제거를 위하여, Producer/Consumer API 활용하여
로직구현 필요