Kafka 운영자가 말하는 처음 접하는 Kafka

저는 국내 메신저 회사에서 우연한 기회로 전사 공용 카프카를 운영하고 있습니다. 현재 기준으로 제가 관리하는 카프카 클러스터는 용도와 종류에 따라  5종류로 구분되고, 전체 서버는 약 50여대 됩니다. 이 수치는 지금도 계속 증가하고 있어 나중에는 더 늘어날 것 같습니다.

제가 글을 적는 이유는 카프카에 대해서 스터디하고 운영하면서 겪었던 일들중에서, 쉽게 이해가 되지 않거나 고민을 했던 부분 그리고 일반적인 검색으로 쉽게 접할 수 없는 내용들을 이해하기 쉽게 공유하려고 합니다.

이번 글에서는 연재의 첫부분으로 Quickstart를 보면서, 제가 이런 내용은 추가해주면 좋을 것 같다고 느낀 부분과 파티션 수에 따른 메시지 순서에 대해서 그림과 같이 알아보겠습니다.

기본개념

카프카에 대해서 처음 접하시는 분들도 계실거 같아서, 간단하게 기본 개념에 대해서 설명하겠습니다. 카프카는 비동기 처리를 위한 메시징 큐의 한 종류이며, 프로듀서와 컨슈머가 있습니다. 대표적인 비동기 메시징 시스템인 메일과 비교하면 이해가 쉽게 될 것 같습니다.

partition-and-consumer-001

우리가 잘 알고 있는 메일의 경우 보내는 사람은 받는 사람과 상관 없이 메일 서버로 메시지를 보낼 수 있습니다. 보낸 메시지는 메일서버에 저장되어 있고, 받는 사람은 자기가 원하는 시간에 언제든지 메일을 볼 수 있게 됩니다.

카프카도 비슷합니다. 프로듀서는 카프카로 메시지를 보내게 되고, 해당 메시지는 카프카에 저장되어 보관중입니다. 그리고 컨슈머는 카프카에 저장되어 있는 메시지를 필요로 할때, 가져갈 수 있습니다.

기본 개념에서 알았으니, 이제 Quickstart를 통해서 카프카에 대해서 살펴보면서, 따라해보겠습니다.

Quickstart

아마 많은 분들이 처음으로 카프카를 접하게 되면, 카프카? 그게 뭐지? 라고 생각하시면서 카프카 홈페이지를 방문을 하실거 같고, 도큐먼트를 읽어보실 것 같습니다. 도큐먼트가 아무래도 영문으로 길게 적혀 있기때문에,  “역시 난 실전이지” 라는 생각으로 Quickstart를 보시고, 순서대로 따라해보실것 같습니다. 저 역시 마찬가지입니다.

Quickstart를 보면서 제가 개인적으로 추가했으면 하는 내용들을 추가하면서 설명하겠습니다. 카프카 설치하기나 config부분은 많은 자료들이 있으니 여기서는 자세히 적지 않겠습니다. 만약 나중에 필요하다고 생각되면 따로 한번 정리하겠습니다.

서버 준비

Document에 있는 Quickstart에서는 서버를 몇대를 어떻게 준비해야 하는 내용도 없어 전 Quickstart를 따라하기 어려웠습니다. 저는 카프카의 간단한 테스트 환경을 위해서 최소 3대가 필요하다고 생각합니다. 테스트 환경이므로, 주키퍼와 카프카를 동일한 서버로 구성해도 괜찮습니다.

  • 주키퍼 – 3EA
  • 카프카 – 3EA

주키퍼는 카프카의 노드 관리를 해주고,  토픽의 offset 정보등을 저장하기 위해 필요합니다. 주키퍼는 과반수 투표방식으로 결정하기 때문에 홀수로 구성해야 하고, 과반수 이상 살아 있으면 정상으로 동작합니다.

ex) 주키퍼 3대일 경우 2대 이상, 주피커 5대일 경우 3대 이상

카프카는 과반수 투표방식을 사용하지 않지만, Replication Factor를 3으로 할 경우 균일하게 스프레드하기 위해서 노드 수 3이 최소라고 생각합니다. (__consumer_offsets 토픽은 기본값이 RF3)

설치

카프카를 다운로드 한후, 압축을 풀면 주키퍼와 카프카가 포함되어 있습니다. 카프카는 스칼라로 만들어져 있고, JVM위에서 동작합니다. 일반적인 JAVA 프로그램과 같이 바이너리 압축 해제 후 약간의 config를 수정 하신 후 실행하면 됩니다.

주키퍼의 경우는 카프카에 포함되어 있는 버전을 사용해도 되고, 오픈소스 버전을 이용해도 됩니다. 지금은 테스트를 위해서 카프카에 포함되어 있는 버전을 이용합니다.

> tar – zxf kafka_2.11-0.10.1.0.tgz
> cd kafka_2.11-0.10.1.0

주키퍼와 카프카의 config 수정을 위해서는 아래 파일들을 수정하면 됩니다.

# 주키퍼 config
vi config/zookeeper.properties
# 카프카 config
vi config/server.properties

서버 시작

서버를 시작할때, 주키퍼 부터 시작해야 합니다. 앞에서 잠깐 설명들였는데, 주키퍼가 카프카의 노드 관리를 하기 때문입니다. 메뉴얼에서 알려주는 것처럼 실행해봅니다.

#주키퍼 시작
> bin/zookeeper-server-start.sh config/zookeeper.properties
# 카프카 시작
> bin/kafka-server-start.sh config/server.properties

실행하고 나서, 다음 순서인 메시지 보내기를 하려고 하니 진행할수가 없습니다. 포그라운드(포그라운드 백그라운드는 관련 자료가 많이 있으니 언급하지 않겠습니다.)로 실행했기 때문입니다. 데몬으로 실행하는 방법은 없는지 검색을 합니다. 아래와 같이 실행하면 데몬으로 실행하게 됩니다.

#주키퍼 데몬 시작
> bin/zookeeper-server-start.sh -daemon config/zookeeper.properties
#카프카 데몬 시작
> bin/kafka-server-start.sh -daemon config/server.properties

나중에 알게된 사실이지만, bin/kafka-server-start.sh 엔터하면 USAGE 부분에서 [-daemon] 이라고 표시해주고 있었습니다.  저는 메뉴얼에서 -daemon 모드에 대해서 언급했으면 하는 마음으로 적어봅니다.

토픽 만들기

카프카에서 토픽은 데이터베이스의 table정도의 개념으로 생각하시면 될 것 같습니다. 카프카에 저장되는 데이터를 토픽이라는 이름으로 구분하기 위해서 사용합니다.  replica 2 or 3은 2개 or 3개로 복제할것인지를 의미하고, partition은 토픽을 몇개로 나눌지를 의미합니다. 여기서는 테스트를 위해 1 replica, 1 partition으로 만들어봅니다. 

> bin/kafka-topics.sh –create –zookeeper localhost:2181 –replication-factor 1 –partitions 1 –topic test
Created topic “test”. -> 이런 메시지가 나타나면,  완료입니다.

커맨드를 이용하여 주키퍼에 해당 토픽이 생성되어 있는지 확인 합니다.

> bin/kafka-topics.sh –list –zookeeper localhost:2181
# consumer_offsets는 offset을 주키퍼가 아닌 카프카의 토픽으로 저장할때 사용하는 토픽이며, 자동으로 생성되는 토픽입니다.
__consumer_offsets
# 방금 만들었던 test 이름의 토픽 잘 생성되었습니다.
test

메시지 보내기

카프카에서는 동작 테스트를 위해서 console-producer를 제공해주고 있습니다. 해당 커맨드를 이용해서 토픽으로 메시지를 보낼 수 있으며 각각의 라인이 하나의 메시지가 됩니다.  아래 예제를 보겠습니다.

> bin/kafka-console-producer.sh –broker-list localhost:9092 –topic test
# 여기부터 메시지를 보내게 됩니다.
This is a message
# 라인이 변경되었으니, 아래 메시지는 2번째 메시지가 됩니다.
This is another message

위 명령어는 console-producer를 이용해서 test라는 토픽으로 2개의 메시지를 보냅니다.

메시지 가져오기

카프카에서는 console-consumer 역시 제공해주고 있습니다. 해당 커맨드를 이용해서 토픽의 메시지를 가져올 수 있습니다. 위에서 보낸 메시지를 가져오겠습니다.

> bin/kafka-console-consumer.sh –bootstrap-server localhost:9092 –topic test –from-beginning
# 여기부터 메시지를 가져오는 것입니다.
This is a message
This is another message

오~ 제가 보냈던 메시지가 잘 보이며, 순서대로 잘 가져왔습니다.
이것으로서 카프카 프로듀서와 컨슈머를 다 경험해본 것입니다. 참 쉽죠?

파티션 수에 따른 메시지 순서

이번 내용은 제가 이해하는데 한참 걸렸던 메시지 순서에 대한 내용입니다. 이 글의 핵심이라고 보셔도 됩니다.
제가 겪었던 내용을 재현하기 위해서, 파티션의 수를 8로 주고 새로운 토픽 test8로 만들어 보겠습니다. 파티션 수를 8로 준것은 큰 의미없이, 카프카 default 값을 따라한 것입니다.

> bin/kafka-topics.sh –create –zookeeper localhost:2181 –replication-factor 1 –partitions 8 –topic test8
Created topic “test8”. -> 완성!!

이제 메시지를 보내보겠습니다. 이해하기 쉽게 문자가 아닌 숫자 하나로 1 ~ 8까지 메시지를 보내보겠습니다.

> bin/kafka-console-producer.sh –broker-list localhost:9092 –topic test8
# 여기서 부터 메시지를 보내게 됩니다.
1
2
3
4
5
6
7
8

동시에 가져오기도 합니다.

> bin/kafka-console-consumer.sh –bootstrap-server localhost:9092 –topic test8 –from-beginning
# 여기부터 메시지를 가져오는 것입니다.
1
3
2
5
4
6
8
7

앗.. 보이시나요? 1 ~ 8까지 순서대로 보냈는데, 1,3,2,5,4,6,8,7로 들어왔습니다.
문제가 있는걸까요? 다시 1 ~ 8까지 순서대로 보내봅니다. 하지만 역시 순서대로 오지 않습니다. 왜 이럴까요?

다음 내용에서 그림과 같이 설명을 이어가도록 하겠습니다.

파티션 수와 메시지 순서에 대한 이해

먼저 그림과 같이 토픽에 파티션 갯수가 1인 경우를 살펴보겠습니다.

partition-and-consumer-001

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

partition-and-consumer-002

다음으로, 파티션에는 데이터 3, 4가 순서대로 들어갔고, 컨슈머는 파티션의 이후 데이터인  2, 3을 가져왔습니다.  이후 컨슈머가 가져오는 데이터는 4라는 것을 예상할 수 있겠죠?

위의 예제에서 알 수 있듯이 하나의 파티션에 대해서 데이터의 순서를 보장합니다. 만약 토픽에 대해 모든 데이터의 순서를 보장받고 싶다면, 토픽을 생성할때 파티션의 수는 어떻게 하면 될까요? 네 맞습니다. 파티션의 수를 1로 토픽을 생성하면 됩니다. 자 이제 파티션의 수가 1이 아닌 4의 경우를 설명하도록 하겠습니다.

partition-and-consumer-003

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

조금 이해가 되시나요? 아래 그림으로 설명 이어나가도록 하겠습니다.

partition-and-consumer-004

이후 해당 토픽에 데이터 4, 5, 6 이 들어오고, 그 데이터는 파티션4의 첫번째, 파티션2와 3의 두번째에 들어왔습니다. 컨슈머는 이후 데이터 즉 4, 5, 6에 대해서도 가져오게 됩니다.  하지만 역시 순서대로 가져오지 않았습니다. 메시지를 가져오는 순서에 대해 파티션 2번으로 추가 설명을 드리겠습니다. 2번 파티션의 첫번째 데이터가 2, 두번째 데이터가 5입니다. 이런 경우에 파티션 2는 앞서 설명드린 파티션1인 경우와 동일하게 두번째 데이터 5가 첫번째 데이터 2 앞으로 올수 없습니다. 그래서 컨슈머가 데이터를 가져올 때, 5는 2보다 절대로 앞에 올 수 없습니다. 마찬가지로 6도 3보다 앞에 올 수 없습니다.

지금까지 설명했던 내용을 바탕으로 컨슈머가 데이터를 가져온 순서대로 정리해 보면 아래 그림과 같습니다.

partition-and-consumer-005

1, 3, 2, 4, 6, 5 순이고, 5는 2보다 뒤에 있고 6은 3보다 뒤에 있습니다. 파티션 수와 메시지의 순서에 대해서 이해가 되셨나요?
최종적으로 정리하자면, 카프카는 각각의 파티션에 대해서만 순서를 보장합니다. 그래서, 위의 첫번째 예제에서 살펴본 것처럼  1개의 파티션인 경우에는 프로듀서가 보낸 순서대로 가져올 수 있지만, 파티션이 8개인 경우에는 프로듀서가 보낸 순서대로 메시지를 가져올 수 없었던 것입니다.

내용이 어렵지는 않았죠? 다음 글에서는 컨슈머 그룹에 대해서 한번 살펴보겠습니다.