본문 바로가기

데이터처리/kafka

카프카의 내부 동작 원리와 구현

내부 동작 원리

- 리플리케이션

- 리더와 팔로워의 역할

- 리더에포크와 복구 동작

카프카 리플리케이션

고가용성 분산 스트리밍 플랫폼인 카프카는 데이터 파이프라인들의 메인 허브 역할을 하는데,

이 카프카가 문제가 생겨 전체 파이프라인에 영향을 미치면 심각한 문제가된다.

 

따라서 일시적인 장애가 발생하더라도 안정적이게 서비스 할 수 있게 

리플리케이션 동작을 하게 됐다.

 

리플리케이션 동작

카프카는 브로커가 장애 나도 안정적인 서비스를 제공함.

이 리플리케이션 동작을 위해 토픽 생성시 replication factor 옵션 설정

 

어떻게 동작을 하는지 알아보자.

 

예제에서는 토픽을 하나 생성하고, (파티션 1, 리플리케이션 팩터 3)

describe 로 상세보기를 했다.

 

그럼 파티션 0에 리더는 브로커1, 리플리케이션은 1,2,3 에 있다고 나오게 된다.

리플리케이션은 토픽이 아니라 토픽을 구성하는 각각의 파티션들이다

 

메시지를 보낸 후 세그먼트가 어떻게 저장되나 보면

브로커 1,2,3 에 모두 동일한 메시지가 세그먼트로 저장되는걸 볼 수 있다.

 

이렇게 N 개의 리플리케이션이면 N-1 개까진 장애가 나더라도 안정적이게 메시지를 보낼수있게 된다.

 

리더와 팔로워

파티션에는 리더와 팔로워가 있다.

리더만의 역할이 따로 있다. 카프카는 내부적으로 모두 동일한 리플리케이션들에서 리더와 팔로우를 구분한다.

모든 읽기와 쓰기는 리더를 통해서만 가능.

프로듀서와 컨슈머는 리더를 통해서만 동작한다.

나머지 팔로워들은 대기하는건 아니고 리더에 문제가 발생했을때 리더가 될 준비를 한다.

컨슈머가 데이터 가져가는거랑 비슷하게 리더에서 새 메시지를 받아서 복제함.

 

복제 유지와 커밋

리더와 팔로워간에 어떻게 복제가 이뤄지는지 알아보자.

 

리더와 팔로워는 ISR 이라는 논리적 그룹으로 묶여있다.

그룹으로 묶는 이유는 이 그룹에서만 리더의 자격을 주기 가질수있기 때문

 

ISR 내의 팔로워들은 리더에 데이터를 팔로우하고, 리더는 모든 팔로워가 받을때까지 기다린다.

팔로워가 만약 장애로 못받고, 이 팔로워가 리더가 되버린다면 데이터의 정합성 문제가 있을수있다.

따라서 리더는 팔로워들을 잘 감시하게 된다.

즉, 리더의 데이터를 잘 따라온 팔로워만 ISR 그룹에 속하게 된다.

 

그럼 리플리케이션 동작을 잘하고 있는지 여부는 누가 판단하고 어떤기준으로 판단할까?

리더가 팔로워가 동작을 잘 수행하고있는지 판단한다.

특정 시기만큼 팔로워가 복제를 안하면 문제가 있다고 판단해 ISR에서 추방한다.

 

ISR내에 모든 팔로워가 복제가 완료되면 리더는 내부적으로 커밋 표시를 한다.

마지막 커밋 오프셋 위치는 하이워터마크 라고 부름

즉 커밋되었다는건 모든 ISR 내의 리플리케이션이 전부 메시지를 저장했다는 뜻.

 

이렇게 커밋된 메시지만 컨슈머가 가져갈수있다.

 

커밋된 위치가 중요하다는걸 알 수 있다.

이 위치는 어떻게 마크해둘까?

모든 브로커들은 재시작할때 커밋된 메시지를 유지하기 위해 디스크에 replication-offset-checkpoint 파일에

마지막 커밋 오프셋 위치 저장.

 

리더와 팔로워의 단계별 리플리케이션 동작

리더는 매우 바쁘다. 읽고 쓰기도 해야하고 , 팔로워들과 통신도 해야하니.

따라서, 성능을 위해 카프카는 리더와 팔로워 간의 리플리케이션 동작을 처리할떄, 서로의 통신을 최소화 할수있게 설계했다.

 

어떻게 동작하는지 단계별로 알아보자.

 

1. 리더에 메시지가 생기면 팔로워들은 리더에 오프셋 메시지 가져오기를 요청 후 새 메시지가 있다는걸 알아차림.

리더는 모든 팔로워가 0번 오프셋에 요청을 보낸걸 알게된다. (팔로워가 잘 가져갔는지 결과는 모름)

 

래빗MQ 에서는 팔로워가 리더에 ACK 를 보내지만, 카프카는그런 통신을 하지 않음.

ACK 를 제거하면서 성능 이득을 높였다.

 

그럼 어떻게 안정적이게 보낼까?

 

2. 리더에 2번째 메시지가 도착했다. 0번 오프셋에 리플리케이션을 마친 팔로워들이 1번 오프셋에대해 리플리케이션를 요청한다.

리더는 1번을 요청한걸 보고 리플리케이션가 성공했다는걸 알수있다.

실패했으면 0번 오프셋에 요청을 했을것이다.

 

리더는 1번 오프셋 메시지에 요청을 한 팔로워에게 0번 오프셋 메시지가 커밋되었다고 알린다.

 

3. 모든 팔로워는 0번이 커밋되었다고 인지하고 리더와 동일하게 커밋한다.

그 후 오프셋 1번을 리플리케이션한다

 

리더가 푸시 하는 방식이 아니라 팔로워들이 풀하면서 리더의 부하를 줄여줬다.

 

리더에포크와 복구

리더에포크(epoch)는 파티션들이 복구 동작을 할때 일관성을 유지하기 위한 용도로 사용된다.

컨트롤러에 의해 관리되는 32비트의 숫자로 표현

 

리더에포크 정보는 리플리케이션 프로토콜에 의해 전달되고,

새로운 리더가 변경된후 변경된 리더의 정보를 모든 팔로워에게 알린다.

리더에포크는 복구 동작 시 하이워터마크를 대체하는 수단으로 활용한다.

브로커가 복구동작을 할 때 왜 리더에포크가 필요한지 알아보자.

 

만약에 리더에포크가 없다면?

장애로부터 복구되는 과정은 이럴것

 

만약 팔로워가 하이워터마크를 올리는 응답을 리더로 부터 못받고

팔로워가 다운 되었다고 가정하자.

 

복구 즉시, 자신이 가진 메시지가 하이워터마크보다 높기때문에 메시지를 바로 삭제시킨다.

만약 이때 리더가 다운이 돼서 유일한 팔로워인 이 노드가 리더가 됐다고 가정하면

높았던 메시지가 유실된것이다.

 

근데 리더에포크를 사용하면?

복구 즉시 메시지를 삭제시키지 않고 리더에 물어본 후 맞는지 확인한다.