💡 Kafka 공식 문서 일부
To make your data fault-tolerant and highly-available, every topic can be replicated, even across geo-regions or datacenters, so that there are always multiple brokers that have a copy of the data just in case things go wrong, you want to do maintenance on the brokers, and so on. A common production setting is a replication factor of 3, i.e., there will always be three copies of your data. This replication is performed at the level of topic-partitions.
내결함성, 고가용성 있는 데이터를 만들기 위해 모든 토픽은 복제할 수 있으며, 지리적으로나 분산시키거나 데이터센터에 걸쳐서도 가능하다. 따라서 혹시 모를 문제를 대비하거나 브로커 유지 관리 등을 위해, 항상 데이터 복제본을 가진 멀티 브로커가 존재하게 된다. 보통 프로덕션 환경에선 Replication Factor 를 3으로 설정한다. 이렇게 하면 항상 데이터 복제본이 3개 존재하게 된다. 데이터 복제는 토픽-파티션 레벨에서 이루어진다.
Kafka에서 Replication Factor는 파티션(partition)에 저장된 데이터가 클러스터 내에서 몇 개의 브로커(broker)에 복제되는지를 나타내는 지표입니다. 이 값은 Kafka의 데이터 고가용성과 내결함성을 보장하기 위해 중요한 역할을 합니다.
- 위 내용의 이해를 위해서, Kafka 의 기본 개념 및 Producer 와 Consumer 의 동작 과정에 대해서 살펴보도록 하겠습니다.
기본 개념
💡 Kafka 공식 소개글
Apache Kafka is an open-source distributed event streaming platform used by thousands of companies for high-performance data pipelines, streaming analytics, data integration, and mission-critical applications.
Apache Kafka는 수천 개의 회사에서 high-performance data pipelines, streaming analytics, data integration, and mission-critical applications을 위해 사용하는 오픈 소스 분산 이벤트 스트리밍 플랫폼입니다.
- 오픈 소스(Open Source) : 소스 코드를 공개해 누구나 특별한 제한 없이 사용, 수정, 배포할 수 있는 오픈 소스 라이선스를 만족하는 소프트웨어
- 분산 (Distributed) : 여러 대의 서버(브로커)가 협력하여 데이터를 처리하고 저장하는 환경
- 이벤트 스트리밍 (Event Streaming) : 이벤트 소스(센서, 데이터 베이스)에서 데이터를 실시간으로 이벤트 스트림 형식으로 수집하여 끊김 없이 처리 후 필요한 곳에 제공하는 방식
- 카프카(Kafka)는 크게 아래의 3가지의 구성 요소로 구성되어 있습니다.
- Kafka Server (브로커)
- Producer
- Consumer
- 우리가 잘 알고 있는 메일과 비교하면 이해가 쉽게 될 수 있습니다.
- Kafka Server (브로커) : Mail Server
- Producer : 보내는 사람
- Consumer : 받는 사람
- 메일의 경우 보내는 사람은 받는 사람과 상관 없이 메일 서버로 메시지를 보낼 수 있습니다. 이후 보낸 메시지는 메일 서버에 저장되어 있고, 받는 사람은 자기가 원하는 시간에 언제든지 메일을 볼 수 있게 됩니다.
- 카프카도 비슷합니다. 프로듀서는 카프카 서버로 메시지를 보냅니다. 이후 해당 메시지는 카프카 서버에 저장되어 보관중입니다. 그리고 컨슈머는 카프카에 저장되어 있는 메시지를 필요로 할 때, 가져갈 수 있습니다.
- 컨슈머가 메시지를 가져갈 때, 카프카 서버에 저장되어 있는 메시지는 삭제되지 않습니다.
(메일을 수신하고 조회 하여도, 메일 서버에서는 메일이 삭제되지 않는다.)
Kafka Server (브로커)
- 프로듀서에 의해 데이터가 저장되고, 컨슈머에게 데이터를 보내주는 카프카 서버에 대해서 먼저 알아보겠습니다.
- 카프카 서버는 단일로도 구성할 수 있으며, 일반적으로 데이터 복제본을 저장하여 안전한 운영을 위해 다수로 구성합니다.
- 실 서비스에는 카프카 브로커를 최소 3대를 사용하는게 좋다는게 일반적인 의견입니다. 이에대해서는 밑에서 자세히 다루도록 하겠습니다.

- 각각의 카프카 서버에 데이터는 아래와 같은 형태로 저장됩니다.

Topic (토픽)
- 카프카에서 토픽은 데이터베이스의 table정도의 개념으로 생각하시면 될 것 같습니다. 카프카에 저장되는 데이터를 토픽이라는 이름으로 구분하기 위해서 사용합니다.
- 프로듀서에서 메시지를 발행 시, 토픽을 지정하여 발행하게 됩니다. 컨슈머는 구독하고 있던 토픽에 발행된 메시지를 수신합니다. 이러한 과정으로 컨슈머는 끊김없이 원하는 메시지를 수신할 수 있게됩니다.
Partition (파티션)
- 파티션은 토픽을 나눠서 병렬 처리를 가능하게 할 수 있는 기본 단위이며, 각 토픽은 하나 이상의 파티션으로 나뉘어져 있습니다.
Topic Replication (토픽 복제본)
- 카프카에서는 각 토픽의 replication factor 수를 조정하여, 복제본(replication)의 수를 몇개로 할지 관리자가 조정할 수 있습니다.
- 아래의 이미지에서
- TOPIC 1은 replication factor 가 3이며, 복제본(자기 자신을 포함)이 3개 생성되어 있습니다.
- TOPIC 3는 replication factor 가 2이며, 복제본(자기 자신을 포함)이 2개 생성되어 있습니다.
- 복제본 수가 많을수록 브로커 장애 발생 시, 토픽에 저장된 데이터 안전성이 보장되기 때문에 replication factor 를 2보다는 3으로 사용하는 것을 권장합니다.
- 데이터의 중요도에 따라 2 또는 3을 선택하여 사용하는 것이 일반적입니다.

Leader & Follower
- 위 구성에서 각 토픽별로 복제본에게 Leader 와 Follower 역할을 부여했습니다.

- Leader
- Topic 으로 통하는 모든 데이터의 read/write 는 오직 Leader 와 이루어집니다.
- Follower
- Leader 가 Down 되었을 시, Follwer 들 중 누구든지 Leader 가 될 수 있습니다.
- 언제든지 Leader 가 될 수 있을 수 있도록, Follower 는 주기적으로 Leader 의 데이터를 풀링하여 동기화를 수행합니다.
💡 Leader 가 Down 되었을 때, 발생하는 동작에 대해서는 아래의 글을 참고해주시기 바랍니다.
Kafka 운영자가 말하는 Topic Replication | Popit
Producer (프로듀서)
- 프로듀서는 카프카 서버로 메시지를 보내고, 이후 해당 메시지는 카프카 서버에 저장되어 보관되게 된다고 하였습니다.
Producer ACKS
- 프로듀서가 카프카 서버에 메시지를 보낼 때, 몇가지의 옵션을 선택하여 보낼 수 있습니다. 이 옵션들 중 가장 중요하고 꼭 이해를 해야 하는 옵션인 ACKS 에 대해서 알아보도록 하겠습니다.
ACKS란?
- ACKS 는 Acknowledgments의 약자로 “승인” 또는 “확인” 이라는 뜻을 가지고 있습니다. 프로듀서가 사용하는 acks 옵션은 간단하게 말해 프로듀서가 메시지를 보내고 그 메시지를 카프카가 잘 받았는지 확인을 할 것인지 또는 확인을 하지 않을 것인지를 결정하는 옵션입니다. acks에 대해 자세히 살펴보아야 하는 이유는 브로커의 config에 따라 생각하는 결과가 달라지는 경우도 있기 때문에 확실하게 개념을 이해하는 것이 중요합니다.
Producer ACKS 의 값
💡 공식 문서에 따르면 ACKS 의 값은 0, 1, -1(=all) 값을 가질 수 있습니다.
- ACKS = 0 인 경우 : 프로듀서는 카프카가 정상적으로 데이터 수신 확인 X (기다리지 않음)
- ACKS = 1 인 경우: Leader 파티션이 정상적으로 데이터 수신 확인
- ACKS = -1 or all 인 경우: Leader 파티션 데이터 수신 + Follower 파티션 데이터 복제 확인
Apache Kafka
- ACKS = 0
- ACKS 값이 0 이라면, 프로듀서는 카프카에게 메시지를 전송하고 Leader가 메시지를 잘 받았는지 확인하지 않습니다. 프로듀서가 메시지를 보내는 동안 leader가 down되면 메시지 손실이 발생하고, 확인하는 과정이 없기 때문에 속도는 가장 빠릅니다. 메시지 손실을 감안하고 빠르게 보내야 하는 경우 사용할 수 있습니다.
- 메시지의 손실을 감안하더라도 빠르게 메시지를 보내야 할 경우에 사용하시면 좋습니다.

- ACKS = 1
- ACKS 값이 1이라면, 프로듀서는 메시지를 전송하고 Leader 가 메시지를 잘 받았는지 기다립니다. Leader가 메시지를 받았기 때문에 메시지 손실율은 ACKS 값이 0일 때 보다 상대적으로 적으며 속도는 조금 더 느립니다.

- ACKS 값이 1이라도 메시지가 손실될 수 있는 경우를 살펴보겠습니다.
1. Leader 가 메시지를 받은 뒤 프로듀서에게 정상 응답을 합니다.
2. 그 후 Follower 가 메시지를 복제하기 전에 Leader 가 Down 된다면 메시지를 손실하게 됩니다.

- ACKS = -1 or all 인 경우
- ACKS 값이 -1 or all 이라면, Leader 이 정상적으로 수신했고 Follower 도 복제가 완료됨을 보장할 수 있습니다. 데이터 손실율은 거의 없지만 기다리는 시간이 길어지기 때문에 가장 느립니다.
- 메시지의 손실률이 매우 중요한 경우에 적합한 옵션입니다.
- 만약 브로커가 3대(1 leader + 2 follower)인 경우 follower 1대만 복제에 실패한다면 프로듀서가 보낸 메시지는 실패할까요?

- 정답은 실패할 수도 있고 아닐 수도 있습니다. 결과는
min.insync.replicas
값에 의해 좌우됩니다.
min.insync.replicas 옵션
- min.insync.replicas 옵션은 프로듀서가 ACKS=all로 설정하여 메시지를 보낼 때, write를 성공하기 위한 최소 복제본의 수를 의미합니다. 이 옵션은 프로듀서의 옵션이 아니고, 브로커의 옵션입니다. (기본값 : 1)
- 몇가지 경우의 수를 살펴보며, 비교적 안전하게 운영할 수 있는 옵션을 알아보도록 하겠습니다.
- Replication Factor = 2, min.insync.replicas = 1

- 위의 그림은 Replication Factor가 2이고, min.insync.replicas가 1인 경우입니다.
- Replication Factor가 2이므로, 파티션에는 Leader 1개와 Follower 1개가 존재합니다. 프로듀서에서 ACKS=all로 설정하고, 메시지를 보내게 되면 파티션의 Leader와 Follower까지 복제가 되기를 기다려야 합니다. 하지만, 브로커에서 min.insync.replicas의 config를 1로 설정하였기 때문에 Follower에게 복제가 이루어지지 않더라도, 파티션의 Leader는 프로듀서에게 확인 응답을 보내게 됩니다. 결과적으로 위와 같은 설정은 브로커 노드 하나가 다운되더라도 실패하지 않고 메시지를 보낼 수 있습니다.
- Replication Factor = 2, min.insync.replicas = 2

- 위의 그림은 Replication Factor가 2이고, min.insync.replicas가 2인 경우입니다.
- Replication Factor가 2이므로, 파티션에는 Leader 1개와 follower 1개가 존재합니다. 프로듀서에서 ACKS=all로 설정하고, 메시지를 보내게 됩니다. 브로커의 min.insync.replicas는 2로 설정되어 있기 때문에 파티션의 Leader를 포함한 Follower까지 복제가 이루어져야 메시지가 성공적으로 write됩니다. 하지만 BROKER 2의 Follower가 복제를 실패하였고, 최소 복제 수min.insync.replicas를 충족하지 못하였기 때문에 Leader는 프로듀서에게 확인 응답을 보낼 수 없게 되었고, 결국 write는 실패하였습니다.
- Replication Factor = 3, min.insync.replicas = 1

- 위의 그림은 Replication Factor가 2이고, min.insync.replicas가 1인 경우입니다.
- Replication Factor가 3이므로, 파티션에는 Leader 1개와 Follower 2개가 존재합니다. 프로듀서에서 ACKS=all로 설정되어 있고, min.insync.replicas는 1로 설정되어 있어, 모든 Follower들이 복제가 실패하더라도 파티션의 Leader는 프로듀서에게 확인 응답을 보낼 수 있습니다. 다시 말씀드리자면, 운영중에 브로커 노드 2개가 다운되더라도 프로듀서가 정상적으로 메시지를 보낼 수 있는 상황입니다.
- Replication Factor = 3, min.insync.replicas = 2
- 가장 안정적인 예제 입니다.

- 위의 그림은 Replication Factor가 3이고, min.insync.replicas가 2인 경우입니다.
- Replication Factor가 3이므로, 파티션에는 Leader 1개와 Follower 2개가 존재합니다. 프로듀서에서 ACKS=all로 설정되어 있고, min.insync.replicas는 2로 설정되어 있습니다. 두개의 Follower중 최소 하나의 Follower만 복제에 성공하게 되더라도, 최소 요구 수 2를 유지할 수 있게 되어 파티션의 Leader는 프로듀서에게 확인 응답을 보낼 수 있습니다. 다시 말해, 브로커 노드 한대가 다운되더라도 프로듀서가 정상적으로 메시지를 보낼 수 있는 상황입니다.

- 위의 그림은 방금 위에서 설명드린 내용과 같이 Replication Factor가 3이고, min.insync.replicas가 2인 동일한 경우입니다.
- 차이점은 2개의 Follower 모두가 복제를 실패했을 경우입니다. 최소 복제 수가 2인데, 모든 Follower들이 복제를 모두 실패하였기 때문에, 파티션의 Leader는 프로듀서에게 확인 응답을 보낼 수 없습니다.
- 실제 운영환경에서 브로커 노드 2개가 동시에 다운되는 일은 거의 발생하지 않습니다. 그래서 Replication Factor를 3으로 운영하시고, 안정적인 구현을 위해서는 min.insync.replicas는 2로 설정하는 것이 가장 바람직하다고 생각됩니다.
- 다만 서비스에 맞게 메시지가 조금 손실되더라도 빠른 속도를 제공하고 싶다면 실무에서 프로듀서의 ACKS 값을 1로 설정하여 사용하는 경우도 많으니 서비스에 맞게 설정하도록 해야 합니다.
Consumer (컨슈머)
- 컨슈머는 카프카에 저장되어 있는 메시지를 필요로 할 때, 가져갈 수 있다고 하였습니다.
파티션 수에 따른 메시지 Consume 순서
- 컨슈머와 관련해서 이해해두면 좋은 파티션 수에 따른 메시지 Consume 순서에 대해서 예시를 보며 알아보도록 하겠습니다.
- Topic 에 파티션 개수가 1인 경우

- 위 그림은 파티션에 데이터 1, 2가 순서대로 들어갔고, 컨슈머를 이용해서 해당 파티션의 첫번째 데이터인 1을 가져왔습니다.

- 다음으로, 파티션에는 데이터 3, 4가 순서대로 들어갔고, 컨슈머는 파티션의 이후 데이터인 2, 3을 가져왔습니다. 이후 컨슈머가 가져오는 데이터는 4라는 것을 예상할 수 있습니다.
- 위의 예제에서 알 수 있듯이 하나의 파티션에 대해서 데이터의 순서를 보장합니다. 만약 토픽에 대해 모든 데이터의 순서를 보장받고 싶다면, 파티션의 수를 1로 토픽을 생성하면 됩니다.
-
Topic 에 파티션 개수가 4인 경우

- 위의 예제는 토픽의 파티션이 4EA이고, 각각의 파티션 마다 첫번째 데이터가 1, 2, 3 하나씩 데이터가 들어갔습니다.
- 컨슈머는 각각의 파티션으로부터 데이터를 하나씩을 가져오게 되고, 순서는 1,3,2 순으로 가져왔습니다.컨슈머는 각각의 파티션에서 첫번째 데이터를 가져올 뿐이지, 파티션의 순서대로 가져오지는 않습니다.

- 이후 해당 토픽에 데이터 4, 5, 6 이 들어오고, 그 데이터는 파티션4의 첫번째, 파티션2와 3의 두번째에 들어왔습니다.
- 컨슈머는 이후 데이터 즉 4, 5, 6에 대해서도 가져오게 됩니다. 하지만 역시 순서대로 가져오지 않았습니다. 메시지를 가져오는 순서에 대해 파티션 2번으로 추가 설명을 드리겠습니다. 2번 파티션의 첫번째 데이터가 2, 두번째 데이터가 5입니다. 이런 경우에 파티션 2는 앞서 설명드린 파티션이 1개인 경우와 동일하게 두번째 데이터 5가 첫번째 데이터 2 앞으로 올수 없습니다. 그래서 컨슈머가 데이터를 가져올 때, 5는 2보다 절대로 앞에 올 수 없습니다. 마찬가지로 6도 3보다 앞에 올 수 없습니다.
-
최종적으로 정리하자면, 카프카는 각각의 파티션에 대해서만 순서를 보장합니다. 그래서, 위의 첫번째 예제에서 살펴본 것처럼 1개의 파티션인 경우에는 프로듀서가 보낸 순서대로 가져올 수 있지만, 파티션이 4개인 경우에는 프로듀서가 보낸 순서대로 메시지를 가져올 수 없었던 것입니다.