파티션
- 파티션: 토픽을 세분화하여 병렬처리를 지원하는 단위
- 토픽 내부를 여러 개로 나누고 나눈 부분을 파티션이라고 한다.
- 하나의 토픽은 1개 이상의 파티션으로 구성되어 있고 독립적이다.
- 독립적이기 때문에 파티션1과 파티션2는 각각 다른 컨슈머가 붙을 수 있다.
파티션과 컨슈머 그룹
- 컨슈머 그룹: 하나의 토픽을 바라보고 다른 파티션을 담당하는 컨슈머들의 그룹
- 만약 컨슈머 그룹 내의 컨슈머 숫자가 파티션보다 크다면?
- 하나의 컨슈머 당 하나의 파티션을 담당하므로 성능 차이는 없다.
- 다만 파티션을 담당하는 컨슈머가 장애가 났을 경우 다른 컨슈머가 대신 파티션을 담당할 수는 있다.
브로커
- 브로커: 카프카 클라이언트와 데이터를 주고받기 위해 사용되는 주체로 하나의 물리서버이다.
- 하나의 브로커는 여러 토픽을 제공한다.
- 만약 하나의 브로커만 바라보는 상황에서 브로커에 장애가 발생한다면?
클러스터
- 클러스터: 브로커들의 집합체
- 브로커 1,2,3은 모두 같은 Topic1을 포함한다.
- 같은 파티션을 가지고 있지만 각각의 브로커에서 하나의 파티션을 리더로 선정하고, 리더 파티션의 브로커와 컨슈머 그룹이 매핑이 되는 구조다.
- 또한 같은 이름을 갖는 파티션들은 사용하지 않는다 하더라도 데이터를 서로 싱크한다.
- 만약 브로커 1이 문제가 발생하면 다른 브로커의 파티션이 리더로 선정되어 컨슈머와 데이터를 주고 받는다.
Replication
- Kafka에서는 높은 가용성과 신뢰성을 위하여 Replication이란 기능을 제공한다. 메시지를 여러 브로커에 복제를 하면 장애 발생 시 다른 브로커로부터 데이터를 얻을 수 있다.
- Replication은 각 Topic의 Partition들을 Kafka Cluster내의 다른 Broker들로 복제하는 것을 말하며 Topic생성 시 Replication의 수를 지정할 수 있다.
- 생성된 Replication은 Leader와 Follower로 나뉘어 ISR(In Sync Replica)이라는 일종의 Replication Group을 형성하여 관리된다.
- kafka에서 병렬성 (parallelation)이 증가하면 처리량이 증가하나, 지연 시간도 같이 증가한다. 기본적으로 브로커는 싱글 스레드로 다른 브로커의 데이터를 복제하므로, 파티션의 수가 많을 수록 복제 시간이 더 오래걸리고 복제가 모두 완료되어야 Consumer가 메시지에 접근할 수 있기 때문이다.
Replication factor
- Topic 단위로 설정할 수 있음. (Default 1)
- Topic 단위로 replication factor를 설정한다 해서 Topic을 replication 하는 것이 아니라, Topic을 이루는 각각의 Partition을 replication 하는 것
3개의 파티션에 1개의 Replication을 적용
kafka-topics.sh --bootstrap-server localhost:9092 --replication-factor 1 --partitions 3 --topic test --create
3개의 파티션에 3개의 Replication을 적용
kafka-topics.sh --bootstrap-server localhost:9092 --replication-factor 3 --partitions 3 --topic test --create
Leader & Follower
- 카프카는 내부적으로 모두 동일한 리플리케이션을 리더와 팔로워로 구분한다.
- 리더는 리플리케이션 중 하나가 선정되며, 일관성을 보장하기 위해 모든 읽기와 쓰기는 리더를 통해서만 가능하다. 즉, 프로듀서는 리더에게만 메시지를 전송하고 컨슈머도 오직 리더로부터 메시지를 가져온다.
- Follower Replica는 Leader replica의 데이터를 복제하여 동일하게 유지하다가 Leader Replica가 중단되는 경우 Follower Replica 중 하나가 해당 Partition의 새로운 Leader Replica로 선출된다.
- 만약 기존 Leader Replica에 예상치 못한 문제가 생겨 새로운 Leader Replica가 선출되어야 하는 상황이 발생했을 때 제대로 데이터를 복제해 오지 못한 Follower Replica가 존재한다면, 해당 개체를 제외한 나머지 Follower Replica 중에서 Leader Replica를 선출해야 한다. 이를 위해서 Kafka에서는 ISR(In Sync Replica)이라는 개념을 도입을 했다.
ISR(In Sync Replica)
- Leader와 Follower는 ISR이라는 논리적 그룹으로 묶여있다. 이렇게 그룹으로 묶는 이유는 기본적으로 해당 그룹 안에 속한 팔로워들만이 새로운 리더의 자격을 가질 수 있기 때문이다.
- 이 그룹은 Leader와 제대로 동기화가 이루어진 Follower들로 구성된다.
- 동기화를 하기 위해 Follower들은 Fetch 요청을 Leader에게 보내고, Leader는 그 응답으로 Follower들에게 메시지를 전송한다. Fetch 요청에는 Follower들이 다음으로 받기 원하는 메시지의 Offset이 포함되며, 항상 수신된 순서대로 처리된다.
- Leader가 중단되는 경우에는 ISR에 속해있는 Follower 중 하나가 Leader replica로 선출된다.
- Follower가 일정 시간 이상 Fetch 요청을 하지 않거나, 요청은 했지만 시간 안에 Leader 의 마지막 Offset의 메시지를 복제하지 못한다면 동기화에 실패한 것으로 간주하여 Leader는 해당 Follower를 ISR에서 제거한다. (Out-Sync-Replica)(해당 시간은 Broker 설정 파일의 replica.lag.time.max.ms 값으로 설정할 수 있다.)
신뢰성 있는 전송 시 Replication
Producer 설정
Configuration | Default | Description |
---|
acks | all | Producer 가 요청을 보내고 Leader 가 Replication의 수신을 확인해야되는 개수 (0= Ack를 받지 않음, 1 = Leader한테만 받음, all= Leader + 모든 Replicas에게 받음 |
enable.idempotence | True | Producer 가 Record 쓰기 작업을 단 한번만 허용할 것인지 멱등성을 보장 |
max.in.flight.requests.per.connection | <=5 | 한 번에 몇 개의 요청(Request)을 전송할 것인지를 결정 |
retries | >0 | Message를 send하기 위해 재시도 되는 횟수 |
ack=all
일 경우 Replication의 개수가 늘어나면 신뢰성은 증가하나 그만큼 많은 파티션의 응답을 받아야 하므로 동기적으로 메시지를 송신 시 처리 속도가 느려진다. 이는 카프카의 비동기 송신으로 해결할 수 있다.
- 또한 ISR의 파티션 수가 너무 많으면 브로커에 문제 발생 시 복구 시간이 더 오래걸린다. 이는 파티션이 많을수록 리더 선출에 오래 걸리기 때문이다.
acks=all 일 때 브로커의 min.insync.replicas=2 설정을 권장하는 이유
- 카프카 문서에서는 손실 없는 메시지 전송을 위해 ack=all, 브로커의 min.insync.replicas=2, Topic의 replication.factor=3을 권장한다.
min.insync.replicas
옵션 값을 올리면 최소 복제본이 올라가니까 손실없는 전송을 위해서 min.insync.replicas=3
으로 설정해야 하는 것이 아닌가라고 생각할 수 있으나, 2로 설정을 권장하는지 알아보자.
min.insync.replicas=2으로 설정했을 때 동작방식
- 프로듀서가
acks=all
옵션으로 리더에게 메세지를 보낸다.
- 리더는 메세지를 받은 후에 저장한다. 브로커 1에 있는 팔로워는 변경된 사항이나 새로 받은 메세지가 없는지를 리더로부터 주기적으로 확인하면서, 새로운 메세지가 전송된 것을 확인하면 자신도 리더로부터 메세지를 가져와서 저장한다.
- 리더는
min.insync.replicas
가 2으로 설정되어 있기 때문에 acks
를 보내기 전 최소 2개의 복제를 유지하는지 확인해야 한다.
- 리더는 프로듀서가 전송한 메세지에 대해 acks를 프로듀서에게 보낸다.
이렇게 보아도 min.insync.replicas
를 3으로 올리면 모든 브로커가 정상적으로 sync가 되는지 확인할 수 있는데, 왜 2로 권장을 하는 것일까?
min.insync.replicas=3으로 설정하고 하나의 브로커에서 오류가 발생한 경우
- 프로듀서는
acks=all
옵션으로 메세지를 전송합니다.
- 브로커 중 팔로워가 위치하고 있는 브로커 하나를 강제로 종료합니다.
- 카프카 서버의 로그를 확인합니다.
- 에러 로그를 확인해보면
Replication Factor가 부족하다
는 내용의 메세지가 나타나게 된다.
- 왜 이런 로그들이 발생하는지 알아보면 우리는
acks=all, min.insync.replicas=3
으로 설정을 하였고, 이렇게 설정한 경우 프로듀서가 토픽의 리더에게 메세지를 전송하게 되면, 리더 + 팔로워 + 팔로워 이렇게 3곳에서 모두 메세지를 받아야만 리더는 프로듀서에게 메세지를 잘 받았다는 확인(ack)
을 보낼 수 있다.
- 하지만 여기서 팔로워 중에 하나인 브로커 하나에 문제가 발생했으니 ISR에는 리더와 팔로워 하나만 남아있는 상태다. 결국 옵션으로 설정한 조건을 충족시킬 수 없는 상황이 발생했기 때문에 위와 같은 에러 로그가 발생하는 것이다.
- 카프카는 브로커 하나가 다운 되더라도 장애 상황없이 서비스를 잘 처리할 수 있도록 구성되어 있는데, 만약
acks=all, min.insync.replicas=3
으로 설정하게 되면 브로커 하나만 다운 되더라도 카프카 메세지를 보낼 수 없는 클러스터 전체 장애와 비슷한 상황이 발생하게 된다.
- 위의 그림 같이
min.insync.replicas
값이 2이고 브로커가 1대에만 문제가 생겼다면 동작하는데 지장을 주진 않지만, 값이 3인 경우에는 문제가 생기게 된다.
이러한 이유로 카프카에서는 손실없는 메세지 전송을 위해 프로듀서의 acks=all
로 사용하는 경우 브로커는min.insync.replicas=2
로 설정하고 토픽은 replication.factor=3
으로 설정하는 것을 권장하는 것이다.
Reference
https://devlog-wjdrbs96.tistory.com/436