Kafka 운영자가 말하는 Topic Replication

이번 글에서는 kafka에서 사용하는 replication에 대해 알아보도록 하겠습니다. 예전부터 해당 내용에 대해 정리해서 글을 올리려고 했었는데, 생각보다 많이 늦어졌습니다. kafka에 대한 예전 글들도 있으니 참고하시면 좋을 것 같습니다.

Kafka 운영자가 말하는 처음 접하는 Kafka
Kafka 운영자가 말하는 Kafka Consumer Group
Kafka 운영자가 말하는 Producer ACKS
Kafka 운영자가 말하는 Kafka 서버 실전 로그 분석
Kafka 운영자가 말하는 TIP

kafka는 다른 애플리케이션 등에서 사용하는 replication과는 조금 다른 개념의 replication 방식을 사용하고 있습니다. kafka replication를 이해하기 위해 kafka에서 사용되는 replication 관련 몇 가지 용어들과 동작 방식 등을 설명하도록 하겠습니다. 그 첫 번째로 먼저 replication factor에 대해 알아보겠습니다.

kafka replication factor

kafka에서는 replication 수를 임의로 지정하여 topic를 만들 수 있습니다. 전에 설명드렸던 Kafka 운영자가 말하는 처음 접하는 Kafka글에서 command를 이용하여 topic를 생성할 때 아래와 같은 명령어를 실행했었습니다.

bin/kafka-topics.sh –create –zookeeper localhost:2181 –replication-factor 1 –partitions 1 –topic test

중간 부분에 replicaion-factor 1 인 부분 보이시죠? 지금 설명드리고자 하는 부분이 바로 이 부분입니다. 예제에서 1로 되어 있는 숫자를 2로 하면 replication 수가 2개 이고, 3으로 하면 replication 수가 3이 됩니다. 이해를 돕기 위해서 그림으로 같이 설명드리도록 하겠습니다.

replication.001

위 그림은 topic01, topic02가 모두 replication factor가 1인 경우입니다. topic01에 대해서 replication factor를 2로 변경해보겠습니다.

replication.002

2로 변경하게 되면, 위의 그림처럼 topic01이 2개가 됩니다. 이번에는 topic02에 대해서 replication factor를 3으로 변경해보겠습니다.

replication.003

위 그림처럼 topic02가 3개가 되었습니다. kafka에서는 이렇게 replication factor 수를 조정하여, replication의 수를 몇 개로 할지 관리자가 조정할 수 있습니다. replication 수가 많을수록 broker 장애 발생 시 topic에 저장된 데이터 안전성이 보장되기 때문에 중요 데이터의 경우 replication factor 수를 2보다는 3으로 사용하는 것를 권장합니다.

참고로 제가 운영하는 환경을 예를 들자면, server.properties 에서 default.replication.factor=2로 설정하여 사용하고 있습니다. 모든 topic를 2로 사용하는 것은 아니고, 데이터의 중요도에 따라 3으로 변경해서 사용하고 있습니다. 이렇게 사용할 수 있는 이유는 replication factor 옵션이 topic별로 설정이 가능하기 때문입니다. replication factor에 대해서는 이제 마무리하고, 이어서 leader & follower에 대해 설명하도록 하겠습니다.

leader & follower

rabbitmq의 경우 복제본이 2개 있는 경우 하나는 master, 나머지는 mirrored라고 표현합니다. 이러한 용어는 애플리케이션들마다 조금씩 다르게 표현하고 있습니다. kafka에서는 leader와 follower라고 표현합니다. 위 그림에서 설명했던 내용으로 leader와 follower를 표시해 보도록 하겠습니다.

replication.004

topic01는 하나의 leader, 하나의 follower로 구성되어 있고, topic02는 하나의 leader와 두 개의 follower로 구성되어 있습니다. kafka는 leader에게 특별한 기능을 부여하였고, 그 기능이 무엇인지 알아보겠습니다.

topic으로 통하는 모든 데이터의 read/write는 오직 leader와 이루어집니다.

위 글을 보시고, 궁금증이 생기실 수 있습니다. leader가 하나뿐인데 만약 leader가 down 된다면? 또는 leader가 있는 broker가 down 된다면 어떻게 되는 걸까? 답은 간단합니다. follower중의 하나가 leader가 되게 됩니다. 이러한 failover 관련 내용은 다음에서 설명드리려고 하는 ISR과 같이 설명하면 좋을 것 같아서 아래 ISR 설명과 같이 자세히 설명드리도록 하겠습니다.

이번 내용에서는 leader/follower라는 용어가 있고, leader만 read/write가 가능하다는 부분만 이해하시면 될 것 같습니다. 이제 ISR(In Sync Replica)에 대해서 설명하도록 하겠습니다.

ISR(In Sync Replica)

ISR이라는 단어는 대부분 생소하실 것 같습니다. 저도 처음에는 잘 이해가 되지 않았습니다. ISR에 대해 쉽게 이해하시려면, replication group이라고 생각하시면 될 것 같습니다. 위에서 replication factor를 설명드리면서, 복제본의 수를 2와 3으로 늘렸는데요 각각의 replication group이 바로 ISR입니다. 그림으로 설명드리겠습니다.

replication.005

위 그림에서 처럼 topic01은 topic01 끼리 group이 되고, topic02는 topic02 끼리 group이 되었습니다. 이제 여기에 조금 전 설명드린 leader/follower를 추가해보겠습니다.

replication.006

위 그림에서 보는 것과 마찬가지로 ISR에는 하나의 leader와 n개의 follower가 존재하게 됩니다. 왜 ISR로 group를 나누고, leader와 follower들을 나누었을까 하고 의문점이 생길 수 있습니다. 이제부터 나오는 몇 가지 내용들을 하나하나 보시면 조금 이해가 되실 것 같습니다. ISR 규칙 한 가지를 말씀드리겠습니다.

ISR내의 모든 follower들은 누구라도 leader가 될 수 있습니다.

바로 이러한 이유 때문에 위에서 말씀드렸던 leader가 down 되거나, leader가 있는 broker가 down 되었을 때, follower 중 하나가 new leader가 되는 것입니다. 물론 follower가 leader와 동기화가 잘 되고 있어야겠죠? 이 부분에 대해서는 아래에서 좀 더 설명드리겠습니다. 지금은 leader가 down 되면서 follower가 new leader가 되는 과정들에 대해 설명드리도록 하겠습니다.

replication.007

위 그림처럼 만약 broker1이 down 되었다고 가정하겠습니다. broker1이 down 되면서 topic01과 topic02에는 변화가 생기게 됩니다. 그런 변화들에 대해 조금 더 자세히 살펴보겠습니다.

replication.008

topic01의 경우 ISR 내 하나의 follower가 남아 있고, ISR 내 follower는 누구라도 leader가 될 수 있는 조건을 충족하기 때문에 follower -> new leader로 변하게 됩니다. 그리고 더 이상의 follower가 없기 때문에 ISR에는 혼자만 포함됩니다. 이때, 일시적으로 follower가 leader가 되는 과정에서 read/write의 timeout이 발생할 수 있겠지만, retry가 일어나면 new leader와 read/write가 가능하기 때문에 장애 상황은 아닙니다.

topic02의 경우 ISR 내 follower 하나가 down 되었고, down 된 follower는 leader가 될 자격이 없기 때문에 ISR에서 제외가 되면서 ISR에는 leader 하나와 follower 하나만 포함되게 됩니다. topic01과 달리 topic02의 leader는 변하지 않았기 때문에 아무런 특이사항 없이 read/write가 계속 일어납니다. 추가 설명을 위해 이번에는 broker2가 down 되었다고 가정해보겠습니다.

 replication.009

topic01의 경우 ISR 내 더 이상 남아 있는 follower가 없기 때문에 leader를 넘겨줄 수 없는 상황이 되었고, topic01는 leader가 없기 때문에 더 이상 read/write를 할 수 없습니다. 즉, topic01의 경우는 read/write가 불가능한 장애 상황이 된 것입니다. topic02의 경우 topic01과 달리 ISR 내 남아 있는 follower가 하나 있기 때문에 new leader로 변경되고, new leader를 통해 read/write가 가능합니다.

위 예제를 통해 ISR 내 broker 또는 topic의 leader가 down 되는 경우 어떻게 follower가 leader로 변경되고 ISR이 변경되는 내용에 대해 설명드렸습니다. 이제 kafka가 이와 같이 동작하기 위해서 kafka 내부적으로 어떤 작업이 이루어지고 있는지 조금 더 자세하게 살펴보겠습니다.

replication.011

먼저 우리가 topic를 만들게 되면, topic이 생성되고 옵션으로 replication factor를 설정하면 replication factor 수에 맞추어 위와 같이 ISR이 구성되게 됩니다. ISR이 구성되면 leader와 follower는 각자의 중요한 역할이 주어지고 그 역할을 수행하기 시작합니다. 각자의 역할은 아래와 같습니다.

leader : follower 중에서 자신보다 일정기간 동안 뒤쳐지면 leader가 될 자격이 없다고 판단하여 뒤쳐지는 follower를 ISR에서 제외시킵니다.
follower : leader와 동일한 데이터 내용을 유지하기 위해서 짧은 주기로 leader로부터 데이터를 가져옵니다.

위와 같이 동작하기 때문에 ISR 내 어떤 follower라도 leader가 될 수 있는 것입니다. 이해하기 쉽게 그림으로 정리해보겠습니다.

replication.012

먼저 leader의 입장에서 보겠습니다. leader는 ISR 내 follower들을 감시하고 자신보다 뒤처지는 follower는 leader가 될 자격이 없다고 판단하여, ISR에서 강제로 제외시키게 됩니다. 추가로 설명을 드리면, broker가 down 되는 경우 ISR 내 follower는 leader로부터 데이터를 가져오지 못하게 되고, 이러한 상황이 일정 시간 지속되면서 leader는 해당 follower가 뒤쳐졌기 때문에 해당 follower에게 leader를 넘길 수 없다고 판단하여, 해당 follower를 제외시키게 되고 ISR이 축소되는 것입니다.

이번에는 반대로, follower 입장에서 보겠습니다. ISR 내 follower는 누구라도 leader가 될 수 있다는 조건이 있기 때문에 follower는 leader와 동일한 데이터를 유지하는 것이 매우 중요합니다. 따라서 follower는 leader를 계속 바라보면서 consumer들이 kafka에서 데이터를 pull로 가져는 것과 동일한 방법으로 주기적으로 데이터를 pull 합니다. 매우 짧은 주기마다 leader가 새로운 데이터를 받았는지 계속 체크하면서 leader와 동기화를 하게 됩니다.

결국 동일한 ISR 내에서 leader와 follower는 데이터 정합성을 맞추기 위해 각자의 방식으로 서로를 계속 체크하고 있는 것입니다. 지금까지 replication에 대해 설명을 드렸고, 이제 어느 정도 이해가 되셨을 거라고 생각됩니다. 이어서 마지막으로 kafka 클러스터에서 모든 broker가 down 되었을 경우에 어떻게 동작하는지 설명드리면서 이번 글을 마무리하겠습니다.

All down

우리는 모두 모든 broker가 down 되는 일이 발생하기를 정말 원하지 않지만 아주 낮은 확률로 발생할 수 있습니다. 그래서 이런 경우를 가정하고 kafka가 어떻게 동작하는지 알고 있다면, 나중에 동일 상황이 발생했을 때 큰 도움이 될 것이라고 생각됩니다. 빠른 이해를 돕기 위해 순서대로 그림과 같이 설명하도록 하겠습니다.

replication.013

첫 번째 그림은 보내는 사람이 파란색 메시지를 보냈고, leader와 두 follower들에게 모두 전달되었습니다. 하지만 파란색 메시지가 전달되자마자 follower를 가진 broker3이 down 되었습니다.

replication.014

두 번째 그림은 보내는 사람이 연두색 메시지를 보냈고, leader와 하나의 follower에게 모두 전달되었습니다. 마찬가지로 연두색 메시지가 전달되자마자 follower를 가진 broker2가 down 되었습니다.

replication.015

세 번째 그림은 보내는 사람이 핑크색 메시지를 보냈고, leader에게만 전달되었습니다. 핑크색 메시지를 받자마자 마지막 broker1 마저 down 되면서, 결국 모든 broker가 down 상태가 되었습니다.

이러한 경우가 발생했을 때, 대응할 수 있는 방법은 두 가지가 있습니다.

1. 마지막까지 leader였던 broker1번이 up이 되고 다시 leader가 될 때까지 기다린다.(모든 데이터를 가지고 있을 가능성이 높다)
2. ISR과 상관없이 누구라도 가장 빨리 up이 되는 topic이 leader가 된다.(데이터 손실이 되더라도 장애 대응이 빠르다)

kafka에서는 2번 방법(kafka 기본값)을 선택하였고, 동작 방식을 설명하기 위해 가장 적은 메시지를 가진 broker 3번이 가장 먼저 up 되는 예제로 설명하겠습니다.

replication.016

파란색 메시지만 가지고 있던 broker3이 가장 먼저 up이 되었고, 새로운 leader가 되었습니다. new ledaer가 된 이후 보내는 사람이 보라색 메시지를 보냈고, leader에게 잘 전달되었습니다.

replication.017

이후 broker1과 broker2가 up이 되었으며, ISR 내 leader가 이미 존재하기 때문에 자동으로 follower로 연결되면서 leader로부터 데이터를 복제하기 시작합니다. 결과적으로 연두색 메시지와 핑크색 메시지는 손실하게 되었습니다.

해당 내용은 kafka의 옵션 설정을 변경하여, 1번 방법으로 대응할 수도 있습니다. 정말 좋아 보이는 1번 방법에 대해 조금 더 이야기해보겠습니다. 1번 방법으로 대응할 경우, 모든 broker가 down 되는 장애 상황이라 할지라도 데이터 손실 가능성이 적기 때문에 좋은 대응방법일 수 있습니다. 하지만 여기에는 조건이 있습니다. 바로 마지막 leader인 broker 1번이 반드시 up이 되어야 하고, 또 가장 먼저 up이 되어야 합니다. 그렇게 되었을 경우 거의 손실 없이 모든 데이터를 복구할 수 있습니다. 하지만 최악의 상황도 같이 고려해야 합니다. 만약 broker1이 기계적인 결함 등의 이유로 up이 안되거나 up이 되는데 오랜 시간이 필요한 경우 장애 상황인 상태로 막연하게 기다려야 하며, 오히려 해당 시간 동안 장애 시간이 길어지게 됩니다. 그래서 저의 개인적인 의견으로는 이러한 장애 상황 발생 시 비록 일부분의 데이터 손실이 발생할 수 있지만, 빠르게 장애 대응이 가능한 2번 방법으로 대응하는 것이 보다 효율적이라고 생각합니다.

kafka 클러스터 전체가 down 되는 경우는 매우 드문 일이 긴 하지만, 이 글을 읽어 보시는 kafka를 사용자분들은 해당 내용을 인지하시고 장애 발생 시 적절한 대응을 하시면 좋을 것 같습니다. kafka에 정말 중요 데이터를 보내는 경우 중요 데이터 topic은 kafka-mirror-maker를 이용하여 다른 kafka로 mirror 하시거나 그 외 다른 방법 등을 고민하시어 추가적인 대응이 필요할 것 같습니다.

이번 글의 내용은 여기까지 입니다. 제 글 읽어 보시고 kafka 사용하시면서 조금이라도 도움이 되면 좋을 것 같습니다. 긴 글 읽어 주셔서 감사합니다.