보장(guarantee)이란 서로 다른 상황에서도 시스템이 지킬 것이라고 약속하는 행동이다. 관계형 데이터베이스가 ACID로 트랜잭션 처리를 약속하듯, 카프카도 약속하는 것이 있다.

카프카가 약속하는 것

카프카가 보장하는 것은 넷이다.

  1. 파티션 안의 메시지들 간에 순서가 보장된다. A 다음에 B를 썼으면 B의 오프셋이 더 크다
  2. 클라이언트가 쓴 메시지는 모든 인-싱크 레플리카에 쓰여진 뒤에야 커밋된 것으로 간주된다
  3. 커밋된 메시지는 최소 1개의 작동 가능한 레플리카가 남아 있으면 유실되지 않는다
  4. 컨슈머는 커밋된 메시지만 읽을 수 있다

여기 나오는 “커밋”은 컨슈머 쪽의 커밋과 이름만 같고 방향이 반대다. 커밋된 메시지는 모든 ISR에 쓰여져서 컨슈머가 읽을 수 있게 된 브로커 쪽 상태이고, 커밋된 오프셋은 컨슈머가 어디까지 받아서 처리를 끝냈는지 카프카에 알리려고 보내는 값이다.

두 번째 보장에는 선택지가 딸려 있다. 프로듀서는 메시지가 완전히 커밋된 다음 응답을 받을지, 파티션 리더에게 쓰여진 다음 받을지, 네트워크로 전송한 다음 바로 받을지를 고를 수 있다.

신뢰성과 맞바꾸는 것

신뢰성 수준은 고정된 값이 아니라 고르는 값이다. 신뢰성과 일관성을 올리면 가용성, 처리량, 지연, 하드웨어 비용 중 무언가를 내준다. 그래서 브로커 설정을 브로커 단위와 토픽 단위 양쪽에서 잡을 수 있게 해두었다. 신뢰성이 필요한 토픽과 그렇지 않은 토픽을 같은 클러스터에 둘 수 있다는 뜻이다.

브로커, 프로듀서, 컨슈머의 몫

무엇을 골랐든 신뢰성은 한 곳에서 무너진다. 브로커에 가장 높은 설정을 걸어도 프로듀서나 컨슈머가 허술하면 데이터는 유실된다. 브로커 쪽은 복제 팩터, 언클린 리더 선출, 최소 인-싱크 레플리카이고, 프로듀서 쪽은 acks 설정과 에러 처리, 컨슈머 쪽은 오프셋 커밋 시점이다. 셋 중 하나라도 빠지면 나머지 둘의 노력이 무의미해진다.

흔들어보는 검증

설정을 확인한 것으로 끝나지도 않는다. 리더를 정지시키면 정상 작동 재개까지 얼마나 걸리는지, 컨트롤러를 재시작하면 어떻게 되는지, 메시지 유실 없이 브로커를 하나씩 재시작할 수 있는지, 한 파티션의 레플리카를 전부 중단시킨 뒤 아웃-오브-싱크 상태가 된 브로커를 살리면 어떻게 되는지를 실제로 흔들어봐야 한다. VerifiableProducerVerifiableConsumer가 이 검증을 위해 들어 있고, 장애 주입용으로는 트록도르(Trogdor) 프레임워크가 있다.

관련

출처