Kafka는 고가용성을 어떻게 유지하는지 알아보자
수많은 Topic의 설정들.. 성능과 가용성에서 엄청난 차이를 만드는 카프카 엔지니어들의 영역이다.
어줍잖게 카프카쓸거면 RabbitMQ로 구현하라는 말은 엔지니어라는 전문 인력이 필요할만큼 어렵고 그 갭이 심하다는 소리이다.
너무 내 식대로 풀어서 메모했던 내용을 토대로 작성한 게시글이라 비난없이 귀엽게 봐주면 된다.
kafka cluster의 일부가 장애 상황에 빠지더라도 전체 시스템에 영향을 주지 않고 계속 작동할 수 있도록 해주는 Partition, RF, ISR 에 대해 알아보자
Partition
topic은 1개 이상의 파티션으로 이루어진다.
하나의 topic에 포함된 메시지들을 물리적으로 분리해서 저장하는 저장소
하나의 메세지가 하나의 파티션에 들어가는 형태 (Not Sharding, Partition)
하나의 메시지를 쪼개서 넣는 샤딩이 아니라, 파티션 하나에 온전한 메세지를 담는다.
Partition이 많을수록 더 많은 데이터를 Consumer에게 줄 수 있어서 처리량이 높다.
많은 물리적 리소스를 활용 가능. 성능 향상
→ Consumer도 당연히 많아져야겠지?
ex) broker 하나에 A topic만 잇고, 거기 안에 파티션이 많다고 성능과 비례할까?
일반적으로 No. 이런 극단적인 상황은 비효율을 유발한다.
bin/kafka-topics.sh –create –zookeeper localhost:2181 –replication-factor 1 –partitions 1 –topic test
파티션의 개수와 성능
하나의 파티션은 하나의 kafka broker에 소속된다(1:1)
broker는 파티션을 여러개 소유할 수 있다.
파티션 개수가 절대적인 성능 요소는 아니다.
→ 하나의 물리적인 broker 퍼포먼스에는 한계가 있으니까.
kafka broker의 수와 최적의 파티션 개수가 핵심적인 요인
Kafka Topic 설계시 고려해야할 것 요약
모든 전제는 충분한 Kafka Broker의 개수
- 파티션의 개수 : Topic을 사용하기 위한 일꾼들
- RF : Produce시 정상적으로 N개 복제
- ISR : Replica들의 복제의 정상 여부를 정의하는 수치
Partition Replica
RF(Replication Factor
)는 복제본의 개수를 의미한다.
하나의 broker에 문제가 생겨도 가용성을 유지할 수 있다.
1보다 RF가 커야지 고가용성을 달성, 클수록 가용성이 높지만 Broker 개수가 충분할때의 이야기
RF가 너무 크면 메모리 낭비가 된다.
Produce할때 지연시간이 길어질수도 있다.
partition-0
에 하나의 메시지가 들어가고, RF가 4면 파티션0에 4개 차는겨
연결된 브로커가 하나면 brocker 고장나면 말짱 도루묵이 되버린다.
그래서 보통 전체 broker 개수보다 적게 파티션을 유지한다. 브로커가 중복된 파티션을 연결하는 셈
broker가 100개면 2≤ RF≤100
Replication Factor
는 3대 이상으로 권장된다. 만약 RF가 2일때 Broker 중 하나가 동작하지 않으면 리더 파티션 하나만 남기 때문이다.
ISR(In-sync Replica)
RF가 커지면 Produce할때도 복제할 데이터가 늘어나요
그럼 지연시간이 길어지는데 그게 싫어?
→ 하나의 Partition에 대한 Replica들이 동기화된 그룹(ISR)
ISR : 동기화되었다고 판단 가능한 Replica들의 그룹
한마디로 replication group
많은 파티션을 포함 → 신뢰성,가용성 향상, 지연시간 증가
적은 파티션을 포함 → 신뢰성,가용성 하락, 지연시간 감소
적절하게 토픽에 Produce 되었다 = 토픽 내 파티션의 모든 ISR 그룹에 복제되었다.
* ISR의 복제가 완료를 보장한다는 의미
Leader & Follwer
Master&Slave나 Primary&Secondary.. 뭐 부르는 방법은 다양한거 같다
모든 데이터의 읽기와 쓰기는 오직 리더 파티션과 이뤄진다. 리더가 down되면 다음 리더를 팔로워중에서 선출.
팔로워와 리더 파티션간의 데이터 동기화를 보장하기 위해서, 리더 파티션은 ISR 내에 존재하는 팔로워들을 감시한다.
자기보다 뒤쳐지는 팔로워는 과감하게 ISR에서 강제로 제외시킨다
강추당하기 싫은 팔로워들은 주기적으로 데이터를 Pull 해둔다.
반대로, ISR 내의 모든 팔로워들은 누구라도 리더가 될 수 있는 셈이다.
Kafka Cluster에서 모든 broker가 종료된 경우
kafka는 데이터의 손실을 최소화하기 위해서 ISR와 상관없이 가장 빨리 up되는 Topic이 Leader가 된다.
broker의 장애 시간이 길어지는 최악의 경우를 생각하면 효율적이다.
min.insync.replicas
옵션은 ack 응답을 보내기 위해 리더가 확인해야할 최소 replication 수
RF와 min.insync.replicas
를 동일하게 설정한다면?
만약 하나의 broker가 다운되면 가용 가능한 브로커는2개인데, 이때 min.insync.replicas=3
라면 리플리케이션 조건을 충족할 수 없어서 에러가 발생한다.
Number of insync replicas for partition [my-topic-rf2,0] is [1], below required minimum [2]
리플리케이션 조건 : 메시지가 성공적으로 기록되었음을 확인하기 위한 조절
데이터 손실 없이 동기화 상태를 유지하기 위한 조건이라고 이해하면 된다
Producer Acks
- acks=0 : 발행시 확인받지 않음 (속도빠름)
- acks=1 : 리더가 메시지 받은지 확인
- akcs=-1(all) : 리더와 팔로워 둘다 기다린다(손실없음)
Kafka Client Producer 3.0
이후로 acks가 all로 기본값으로 설정되었고 Broker로 단 한번만 record를 전송할 수 있게 되었다.
여담으로, default값인 acks=all
옵션은 max.in.flight.requests.per.connection=3
로 설정하고 비동기 프로듀서를 사용하면 akcs=1과 동일한 성능을 낼 수 있음을 증명했다고 한다.
Brocker로부터의 응답을 비동기로 받으면 max.in.flight.requests.per.connection
개수만큼 병렬로 레코드를 전송하면 된다.
비동기 프로듀서로 전송하는 로직은 다음과 같다.
KafkaProducer<String, String> producer = new KafkaProducer<>(configs);
ProducerRecord<String, String> record = new ProducerRecord<>(my-topic, message); producer.send(record);
producer.send(record, new ProducerCallback());
그래서 Kakfa의 Topic은 replication.factor=3
, min.insync.replicas=2
를 권장한다.
https://blog.voidmainvoid.net/507
카프카 프로듀서의 acks=all 옵션은 사실(?) 느리지 않다!
카프카 3.0 부터는 카프카 프로듀서의 acks 옵션이 all로 지정됩니다. acks=all이 기본값으로 지정된 이유 중 하나는 프로듀서와 브로커 간 통신을 멱등성(idempotence)있게 만들기 위함입니다. 프로듀서
blog.voidmainvoid.net
AWS EC2 오류 - Cannot allocate memory
AWS EC2 환경에서 Kafka를 설치하면 메모리 부족에 의한 Cannot allocate memory
오류를 어렵지 않게 발견할 수 있다.
bin/kafka-server-start.sh
if [ "x$KAFKA_HEAP_OPTS" = "x" ]; then
export KAFKA_HEAP_OPTS="-Xmx1G -Xms1G"
fi
bin/zookeeper-server-start.sh
if [ "x$KAFKA_HEAP_OPTS" = "x" ]; then
export KAFKA_HEAP_OPTS="-Xmx512M -Xms512M"
fi
Kafka의 기본 Heap 메모리는 1G, zookeeper의 Heap메모리는 512M
AWS EC2에서 무료로 제공하는 t2.micro
환경에서는 kafka를 돌릴 수 없단 소리
해당 코드는 보이듯이, KAFKA_HEAP_OPTS
를 따로 설정하지 않으면 Default 값으로 설정한다.
명령어를 통해 변수를 등록하여 힙메모리를 설정하거나 .bashrc에 명령어를 저장해두면 된다. 그래서 그냥 난 EC2안쓰고 도커로 연다.
출처 및 인용
https://www.popit.kr/kafka-운영자가-말하는-topic-replication/