일반화된 유형의 데이터를 발행하고 구독할 수 있는 중앙 집중화된 시스템. 저장된 메시지는 순서를 유지한 채 지속성 있게 보관되고, 여러 번 읽을 수 있다.
링크드인이 막힌 지점
링크드인이 실제로 막힌 지점에서 나왔다. 지표 수집은 폴링 방식이라 간격이 길었고, 애플리케이션 담당자가 자기 지표를 직접 관리할 수 없었으며, 같은 측정값도 시스템이 다르면 이름이 달라져 일관성이 깨졌다. 사용자 활동 추적은 프론트엔드가 XML 배치를 주기적으로 쏟아붓는 방식이라 파싱에 컴퓨팅 자원을 많이 썼고, 시간 단위로 처리되어 실시간으로 쓸 수가 없었다. ActiveMQ를 대안으로 써봤지만 규모 확장성이 부족했고 브로커를 정지시키는 결함이 많았다.
그래서 만든 것이 push-pull 모델로 프로듀서와 컨슈머를 분리하고, 다수의 컨슈머가 쓸 수 있도록 데이터를 영속적으로 저장하고, 데이터가 늘면 scale-out 되는 시스템이다. 2020년 7월 기준으로 매일 7조 개의 메시지를 쓰고 5페타바이트가 넘는 데이터를 읽는다.
분산 커밋 로그라는 이름
이름은 커밋 로그에서 왔다. 파일시스템과 데이터베이스의 커밋 로그는 모든 트랜잭션 기록을 지속성 있게 보존해서 시스템 상태를 일관성 있게 복구할 수 있게 한다. ACID의 D와 C다. 카프카가 하는 일이 같고 분산되어 있으니 분산 커밋 로그다. 이 이름이 가장 좋은 관점이다. 카프카는 메시지 큐가 아니라 읽을 수 있는 로그다.
네 겹의 구조
구조는 네 겹이다. 클러스터 안에 브로커가 여럿 있고, 브로커가 파티션을 나눠 맡고, 파티션은 append-only 로그라서 그 안의 메시지가 오프셋을 하나씩 받는다. 토픽은 파티션들을 묶어 부르는 논리적 이름이고 DB의 테이블 자리에 놓인다. 클라이언트 쪽에서는 프로듀서가 쓰고 컨슈머가 읽는다.
다중 프로듀서와 다중 컨슈머
여러 프로듀서가 같은 토픽에 쓸 수 있다. MSA에서 모든 서비스가 공통 형식으로 쓰는 페이지 뷰 토픽을 하나 두면 컨슈머는 사이트 전체의 페이지 뷰 스트림 하나만 읽으면 된다.
여러 컨슈머가 서로 간섭 없이 같은 스트림을 읽는다. 큐 시스템과의 결정적 차이가 여기다.
디스크 기반 보존
메시지가 디스크에 남으므로 컨슈머가 항상 실시간으로 읽고 있을 필요가 없다. 처리가 느려도, 트래픽이 몰려도 데이터가 유실되지 않는다. 보존 규칙은 토픽별로 잡을 수 있어서 스트림마다 다른 기간을 준다.
성능과 확장
성능은 발행된 메시지가 컨슈머에 닿기까지 1초가 걸리지 않는 수준이다. 개발 환경의 브로커 세 대짜리 클러스터에서 운영 환경의 수백 대짜리 다중 클러스터까지 같은 방식으로 늘린다. 클러스터를 작동 중에 확장하는 방법은 따로 본다.
활용 사례
활동 추적이 카프카가 태어난 이유다. 페이지 뷰와 클릭 같은 수동적인 정보부터 사용자가 프로필에 직접 넣은 정보까지 프론트엔드가 메시지로 만들어 발행하면, 백엔드가 보고서를 만들거나 기계 학습에 넣거나 검색 결과를 갱신한다.
메시지 교환은 알림 발송을 한곳에 모으는 것이다. 각 애플리케이션은 형식과 전송 방법을 신경 쓰지 않고 메시지만 만들고, 포매팅과 여러 건을 묶어 보내기, 사용자가 원하는 수신 방식 적용은 읽는 쪽 하나가 처리한다.
지표와 로그 수집에서는 로그 저장 시스템을 바꿔도 프론트엔드나 수집 방법을 건드리지 않는다. 같은 스트림을 모니터링 시스템도 읽고, 장기 분석용 하둡도 읽고, 엘라스틱서치도 읽는다.
커밋 로그 활용은 DB 변경점을 스트림으로 발행하는 것이다. CDC가 이것이고, 보존 기능이 체인지 로그의 버퍼가 되어 컨슈머가 실패해도 다시 읽으면 된다. 로그 압착은 그것을 더 오래 남긴다.
스트림 처리는 메시지가 생기자마자 처리하는 쪽이다. 오랜 시간 누적된 데이터를 다루는 하둡의 맵리듀스와 대비되는 자리에 있다.
클러스터 경계
복제 메커니즘은 하나의 클러스터 안에서만 작동하도록 설계되었다. 데이터 유형별 분리, 보안 격리, 재해 복구를 위해 클러스터를 여럿 두더라도 그 사이를 잇는 것은 미러메이커 같은 별도 툴의 몫이다.