카프카(kafka) 기본 개념 이해하기 (replication, partition, segment)

해당 내용은 '실전 카프카 개발부터 운영까지' 책을 통해 공부하고 정리한 내용입니다.

 

리플리케이션 (replication)

카프카에서 리플리케이션이란 각 메시지들을 여러 개로 복제해서 브로커들에게 분산시키는 동작을 말한다.

이러한 리플리케이션 덕분에 하나의 브로커에 문제가 발생하더라도 다른 브로커를 통해서 처리가 가능하기 때문에 안정성을 유지할 수 있다.

 

카프카에서 토픽을 생성하는 명령어에서 --replication-factor 3 이라는 옵션이 있는데 이 옵션은 카프카 내에서 몇개의 리플리케이션을 생성하겠다는 의미이다. 예를 들어, replication-factor 가 1 이면 리플리케이션이 1개 있다는 뜻이고 3이면 3개가 있다는 뜻이다.

 

만약 3개의 브로커를 생성해서 TEST 라는 토픽을 3개의 리플리케이션을 생성한다고 하면 각 브로커마다 TEST 라는 토픽을 가지고 있게 된다. 정확하게는 토픽이 리플리케이션 되는 것이 아니라 토픽의 파티션이 리플리케이션이 되는 것이라고 한다.

 

리플리케이션의 팩터 수가 증가하면 당연히 안정성이 높아지겠지만 그만큼 브로커의 리소스를 많이 잡아먹기 때문에 최대한 브로커를 효율적으로 사용할 수 있도록 적절한 팩터 수를 지정하는 것이 효율적이다.

 

토픽을 생성할 때 리플리케이션을 생성하는 기준을 세워두라고 적혀있는데 다음과 같았다.

 

- 테스트나 개발 환경 : 리플리케이션 팩터 1개

- 운영 환경에서 로그성 메시지나 약간의 유실 허용 : 리플리케이션 팩터 2개

- 운영 환경에서 절대 유실되면 안되는 메시지 : 리플리케이션 3개

 

그 외에 4개, 5개까지 늘릴 수도 있지만 저자의 운영 경험상 팩터가 3일 경우에도 충분히 안정성을 보장할 수 있고 적절한 디스크 공간을 사용할 수 있었다고 한다. 내가 생각해봐도 리플리케이션을 4개, 5개까지 설정할 일이 있을까? 하는 생각이 들었다.

 

파티션 (partition)

하나의 토픽이 한 번에 처리할 수 있는 한계를 높이기 위해서 토픽 하나를 여러 개로 나누어서 병렬 처리가 가능하게 만드는 것을 파티션이라고 한다. 하나의 토픽을 여러 개로 나누면 분산 처리가 가능하다. 나누어진 파티션 개수만큼 컨슈머를 연결할 수 있다. 

 

파티션은 0 부터 시작해서 1, 2 와 같이 구분된다. 예를 들어, 3개의 파티션으로 나누어진 TEST 라는 토픽은 TEST-0, TEST-1, TEST-2 와 같이 3개의 파티션으로 나누어진다고 볼 수 있다.

 

파티션 수도 리플리케이션과 동일하게 토픽을 생성할 때 옵션으로 설정할 수 있다. (예시: --partition 1)

파티션 수를 정해야하는데 어떻게 정하는 것이 좋을까? 구글링을 해보면 여러가지 방법이나 공식에 의해 파티션을 나누는 것을 찾아볼 수 있었는데 각 메시지의 크기나 초당 메시지 건수 등에 따라 달라지기 때문에 정확하게 예측하기는 어렵다고 볼 수 있다.

 

파티션을 늘릴 때 유의해야할 점은 초기에 파티션을 생성할 때 언제든지 늘리는 것은 가능하지만 줄이는 것은 절대로 할 수 없다는 것이다. 보통 2 또는 4 정도로 생성한 후에 메시지 처리량이나 컨슈머의 LAG 등을 모니터링하면서 조금씩 늘려가는 것이 가장 좋은 방법이라고 한다.

 

LAG 라는 것을 처음 들어보는데 LAG프로듀서가 보낸 메시지의 수(카프카에 남아있는 수) - 컨슈머가 가져간 메시지의 수 를 나타내는 지표라고 할 수 있다. 만약에 LAG 가 3 이라면 지연이 된다고 볼 수 있고 0 이라면 지연 없이 모든 메시지를 처리했다고 볼 수 있다. 카프카에서 모니터링을 운영할 때 참고라는 지표라고 하니 알아두면 좋을 것 같다.

 

세그먼트 (segment)

그럼 실제로 카프카에서는 토픽을 생성해서 메시지를 전송했고 컨슈머에서 읽을 수 있다고 했는데 실제 메시지는 카프카에서 어디에 저장되고 있는걸까? 프로듀서에서 보낸 메시지는 토픽의 파티션에 저장되어 있다고 한다. 예를 들어 파티션이 3개라면 파티션0 에 메시지가 들어있다.

 

이와 같이 프로듀서에 의해 브로커로 전송된 메시지는 토픽의 파티션에 저장되며, 각 메시지들은 세그먼트라는 로그 파일의 형태로 브로커의 로컬 디스크에 저장된다.

 

세그먼트의 위치는 /data/kafka-logs 라는 디렉토리 내에서 확인할 수 있다고 하는데 나는 AWS 환경이 아닌 로컬 환경에서 도커를 기반으로 실습을 하고 있기 때문에 도커 컨테이너에 접속해서 /var/lib/kafka/data 디렉토리에서 확인할 수 있었다.

 

- ec2 : /data/kafka-logs

- docker : /var/lib/kafka/data

 

도커 컨테이너에서 확인한 결과

$ pwd
/var/lib/kafka/data

$ ls
__consumer_offsets-0   __consumer_offsets-16  __consumer_offsets-23  __consumer_offsets-30  __consumer_offsets-38  __consumer_offsets-45  __consumer_offsets-8		    topic-test-0
__consumer_offsets-1   __consumer_offsets-17  __consumer_offsets-24  __consumer_offsets-31  __consumer_offsets-39  __consumer_offsets-46  __consumer_offsets-9
__consumer_offsets-10  __consumer_offsets-18  __consumer_offsets-25  __consumer_offsets-32  __consumer_offsets-4   __consumer_offsets-47  cleaner-offset-checkpoint
__consumer_offsets-11  __consumer_offsets-19  __consumer_offsets-26  __consumer_offsets-33  __consumer_offsets-40  __consumer_offsets-48  log-start-offset-checkpoint
__consumer_offsets-12  __consumer_offsets-2   __consumer_offsets-27  __consumer_offsets-34  __consumer_offsets-41  __consumer_offsets-49  meta.properties
__consumer_offsets-13  __consumer_offsets-20  __consumer_offsets-28  __consumer_offsets-35  __consumer_offsets-42  __consumer_offsets-5   recovery-point-offset-checkpoint
__consumer_offsets-14  __consumer_offsets-21  __consumer_offsets-29  __consumer_offsets-36  __consumer_offsets-43  __consumer_offsets-6   replication-offset-checkpoint
__consumer_offsets-15  __consumer_offsets-22  __consumer_offsets-3   __consumer_offsets-37  __consumer_offsets-44  __consumer_offsets-7   test-0

 

내가 예전에 생성했던 topic-test 라는 토픽의 디렉토리를 확인해보았다. topic-test-0 이라는 디렉토리 이름을 확인할 수 있었는데 0번 파티션이라고 보면 된다.

$ cd topic-test-0
$ ls
00000000000000000000.index  00000000000000000000.log  00000000000000000000.timeindex  00000000000000000004.snapshot  leader-epoch-checkpoint  partition.metadata

 

프로듀서를 통해 보낸 메시지를 확인하기 위해서는 .log 파일을 통해서 확인할 수 있는데 hexdump 를 보여주는 xxd 명령어를 통해서 파일의 내용을 확인할 수 있다고 한다.

$ cat 00000000000000000000.log
G?ت???_h=??_h=*제이로�그G!?????_????_??*제이로JAYLOG<D??+??_????_?test:tq??_????_??HI[appuser@62e9cbe98669 topic-test-0]$

 

세그먼트 로그 파일을 확인해보니 내가 프로듀서를 통해 보냈던 메시지가 나오는 것을 확인할 수 있었다.

 

지금까지 정리한 내용을 토대로 전체적인 과정을 다시 되짚어보자.

먼저 프로듀서는 카프카의 토픽을 통해 메시지를 전송한다.

토픽은 파티션이 하나뿐이라 프로듀서로 부터 받은 메시지를 파티션 0의 세그먼트 로그 파일에 저장한다.

브로커의 세그먼트 로그 파일에 저장된 메시지는 컨슈머가 읽어갈 수 있다.

 

이러한 과정을 책에서는 아래와 같이 나타내주고 있다.

etc-image-0

 

이렇게 메시지를 어떻게 저장하고 가져가는지에 대해서 리플리케이션과 파티션 그리고 세그먼트까지 기본 개념을 정리해봤다.

기본 개념인 만큼 카프카를 사용하면서 당연하게 이해하고 있어야 하는 내용이라고 생각이 들었고 어느 정도는 데이터 엔지니어링 공부를 하면서 익숙했던 개념들이기도 하고 쉽게 이해할 수 있었는데 이 외에도 여러 개념들이 많이 들어있기 때문에 하나씩 꼼꼼하게 다시 이해하고 넘어가야 할 것 같다.