하나의 메시지를 여러 레플리카에 씀으로써 크래시가 나도 메시지의 지속성을 유지하는 것. 카프카 신뢰성 보장의 핵심이다.

리더와 팔로워

각 파티션은 여러 레플리카를 가질 수 있고 그중 하나가 리더다. 파티션을 담당하는 브로커가 파티션 리더고 나머지 복제본이 파티션 팔로워다. 모든 프로듀서는 리더에 써야 하고, 컨슈머는 기본적으로 리더에서만 읽는다. 팔로워는 리더와 동기화를 맞추면서 최신 이벤트를 제때 복사해 온다.

리더에 장애가 나면 팔로워 중 하나가 리더를 이어받는다. 아무나 되는 것은 아니고 인-싱크 레플리카(ISR)여야 한다. 리더 자신과, 아래 조건을 만족하는 팔로워가 ISR이다.

  • 주키퍼와 활성 세션이 있는가. zookeeper.session.timeout.ms 안에 하트비트를 보낸 적이 있는가
  • replica.lag.time.max.ms 안에 리더로부터 메시지를 읽어온 적이 있는가
  • 그 안에 읽어온 것이 가장 최근 메시지인가

셋째 조건이 핵심이다. 그 시간 동안 랙이 없었던 적이 한 번은 있어야 한다는 뜻이다. 랙은 팔로워가 리더로부터 얼마나 뒤처져 있는지로, 리더의 최신 오프셋이 105이고 팔로워가 102까지 읽었으면 랙은 3이다. 랙이 있다는 것은 이미 뒤처졌다는 것이므로, 한 번도 따라잡지 못했으면 자격을 잃는다.

인-싱크와 아웃-오브-싱크

인-싱크가 아니면 아웃-오브-싱크다. 그런데 아웃-오브-싱크가 무조건 나쁜 것은 아니다.

동기화가 살짝 늦은 인-싱크 레플리카는 프로듀서와 컨슈머를 느리게 만든다. 메시지가 커밋되기 전에 모든 인-싱크 레플리카가 그것을 받을 때까지 양쪽이 기다려야 하기 때문이다. 반대로 아웃-오브-싱크 레플리카는 성능에 영향을 주지 않는다. 더 이상 기다려주지 않으니까. 대신 파티션의 실질적인 복제 팩터가 줄어서 중단 시간이 길어지고 유실 위험이 올라간다.

카프카 예전 버전에서는 인-싱크와 아웃-오브-싱크를 빠르게 오가는 일이 흔했다. 최대 요청 크기가 커서 JVM 힙을 많이 잡고 있으면 GC 시간이 길어지면서 순간적으로 주키퍼 연결이 끊어졌기 때문이다. 큰 메시지를 쓴다면 튜닝이 필요하다.

복제 팩터 결정

replication.factor가 N이면 N-1개의 브로커가 죽어도 읽고 쓸 수 있다. 몇으로 잡을지는 다섯 가지를 저울질해서 정한다.

  • 가용성은 레플리카가 1개면 브로커를 재시작하기만 해도 작동 불능이 된다는 문제다
  • 지속성은 레플리카가 1개인데 디스크가 죽으면 그 파티션 데이터가 전부 사라진다는 문제다
  • 처리량은 복제 트래픽이다. 10Mbps로 쓰는 파티션에서 레플리카 2개면 복제 트래픽 10Mbps, 3개면 20Mbps다
  • 종단 지연은 컨슈머가 읽으려면 모든 ISR에 복제되어야 한다는 데서 온다. 레플리카가 많을수록 하나가 느려져 전부 느려질 가능성이 높다
  • 비용은 N개의 복사본이 N배의 디스크와 네트워크를 쓴다는 것이다

일반적인 결론은 3이다. 중요하지 않은 데이터는 2로 낮춰 저장 비용을 아낀다. min.insync.replicas와의 관계에서 이 숫자가 왜 3인지 한 번 더 좁혀진다.

레플리카가 어디 있는지도 중요하다. 카프카는 같은 파티션의 레플리카를 언제나 서로 다른 브로커에 저장하는데, 그 브로커들이 같은 랙에 꽂혀 있으면 랙 스위치 하나가 죽었을 때 복제 팩터와 상관없이 파티션 전체가 죽는다. broker.rack에 랙 이름을 잡아주면 서로 다른 랙에 분산된다.

참고

원본은 컨슈머가 리더든 팔로워든 어디서 읽어도 된다고 적었다. 팔로워 페치는 2.4.0의 KIP-392로 들어온 기능이고, 브로커에 replica.selector.class를, 컨슈머에 client.rack을 잡아야 동작한다. 기본값은 리더에서만 읽는 것이다. KIP-392

ISR 판정 기준을 6초와 10초로 적은 것도 2.5.0 이전 값이다. KIP-537이 zookeeper.session.timeout.ms를 6000에서 18000으로, replica.lag.time.max.ms를 10000에서 30000으로 올렸다. 클라우드 환경의 네트워크 지연 변동폭을 견디게 하려는 변경이고, 그만큼 컨슈머가 커밋된 메시지를 보기까지 최대 30초를 기다릴 수 있다는 뜻이기도 하다. KIP-537

관련

출처