최소 몇 개의 레플리카가 인-싱크여야 쓰기를 받을 것인가. min.insync.replicas, 기본값은 1이다.
ISR이 리더 하나만 남을 때
“데이터가 커밋되었다”는 모든 인-싱크 레플리카에 쓰여졌다는 뜻이다. 그런데 여기서 “모든”이 1개일 수도 있다. 팔로워들이 죽거나 뒤처지면 리더 혼자 ISR이 되고, 그 상태에서도 메시지는 정상적으로 커밋된다. 그리고 그 하나가 작동 불능에 빠지면 데이터가 사라진다.
“모든”이라는 말이 안전을 보장하지 못하는 지점이고, 그래서 최소 개수를 따로 정한다.
쓰기가 멈추고 읽기만 남는 상태
레플리카 3개에 min.insync.replicas = 2인 경우를 보자. 프로듀서는 3개 중 최소 2개가 인-싱크인 파티션에만 쓸 수 있다. 2개가 작동 불능에 빠지면 브로커는 더 이상 쓰기 요청을 받지 않고, 데이터를 보내려던 프로듀서는 NotEnoughReplicasException을 받는다. 그런데 컨슈머는 이미 존재하는 데이터를 계속 읽을 수 있다. 살아남은 레플리카가 사실상 읽기 전용이 되는 것이다. 여기서 회복하려면 아웃-오브-싱크 레플리카가 재시작하고 복구해서 리더를 따라잡을 때까지 기다려야 한다.
acks=all과의 조합
이 설정 혼자서는 반쪽이라 `acks=all`과 함께 써야 의미가 생긴다. 브로커 쪽에서 “2개는 있어야 받는다”고 하고 프로듀서 쪽에서 “ISR 전부가 받을 때까지 기다린다”고 하면, 쓰기가 성공하기 위해 최소 두 개(리더 하나, 팔로워 하나)가 응답해야 한다. 막으려는 것은 리더가 쓰기에 응답하고, 리더에 장애가 나고, 최근의 성공한 쓰기를 복제받지 못한 다른 레플리카로 리더가 넘어가는 흐름이다.
복제 팩터와의 간격
복제 팩터는 이 값보다 최소 1 이상 크게 잡을 것이 강력히 권장된다. 2 크게 잡는 것을 RF++라고 부르는데, 일부러 정지시킨 레플리카와 예상치 못하게 정지된 레플리카가 동시에 하나씩 발생해도 장애가 나지 않기 때문이다. 롤링 업데이트 중에 하드웨어 장애가 겹치는 상황이 정확히 이 경우다. 그래서 복제 팩터를 몇으로 잡을 것인가의 답이 3으로 좁혀진다.
값을 높일 때의 오버헤드
값을 높이면 오버헤드가 늘어 성능이 떨어진다. 메시지 몇 개 유실은 괜찮고 높은 처리량을 받아내야 하는 클러스터라면 기본값 1에서 바꾸지 않는 쪽이 권장된다.