Search

카프카 핵심 가이드 ch.1

1.1 발행/구독 메시지 전달

카프카는 발행자와 구독자 패턴으로 메시지 큐를 관리합니다. 이를 중간에서 중계해주는 중간 지점을 브로커라고 합니다.
서비스가 발전하며 지표(데이터)를 생성하는 서비스가 하나, 둘 이상이 되며 다양한 정보를 다양한 서버에 전송하는 구조가 될 수 있습니다.
이러한 구조는 기술 부채를 유발하기에 다음과 같은 발행/구독 시스템이 발명되게 되었습니다.
1.1.2 개별 메시지 큐 시스템
프론트에서 사용자 로그를 추적해 ML개발자에게 공하거나 관리자용 보고서를 생성하는데 사용해야하는 경우가 있습니다. 이러한 경우에 비슷한 시스템을 구성함으로써 정보의 발행자와 구독자를 분리할 수 있습니다.
과거의 시스템은 위와 같이 여러 발행/구독 브로커를 두고 관리하였지만, 이는 각각의 큐에 대한 중복이 많습니다. 이를 개선하기 위해 중앙 집중화된 카프카가 등장하게 됩니다.

1.2 카프카 입문

카프카는 발행/구독 시스템분산 커밋 로그라고 불리기도 합니다.
카프카는 저장된 데이터의 순서를 보장한 채로 지속성 있게 보관되며 읽을 수 있습니다. 또한 확장 시 성능을 향상시키고 실패가 발생하더라도 데이터 사용에는 문제가 없도록 시스템 안에서 데이터를 분산시켜 저장할 수 있습니다.
여러 클러스터로 나뉜 카프카에도 데이터의 순서는 보장되는가?
1.2.1 메시지와 배치
카프카의 데이터의 기본 단위는 메시지입니다. 단순한 바이트의 배열을 의미하기도 합니다. 데이터에는 와 밸류로 나뉘어 저장됩니다.
카프카는 효율성을 위해 메시지를 배치단위로 저장합니다. 같은 토픽의 파티션에 쓰여지는 메시지들의 집합을 의미합니다.
메시지를 배치 단위로 처리함으로써 네트워크 I/O를 줄일 수 있습니다. 이를 사용할 때 지연과 처리량 사이의 트레이드오프를 유의해야 합니다.
1.2.2 스키마
카프카의 입장에서 메시지는 단순한 바이트 배열일 뿐이지만, 내용을 이해할 수 있도록 일정한 구조를 부여하는 것이 권장됩니다.
흔히 아는 JSONXML이 있습니다. 하지만 이 방식들은 타입 처리 기능이나 스키마 버전 간의 호환성 유지 기능이 떨어집니다.
⇒ 따라서 많은 카프카 개발자들은 아파치 에이브로(Avro)를 선호합니다.
이 직렬화 프레임워크는 본래 하둡을 위해 개발되었습니다. 에이브로는 조밀한 직렬화 형식을 제공하는 데다 메시지 본체와 스키마를 분리하기 때문에 스키마가 변경되더라도 코드를 생성할 필요가 없습니다.
Avro = schema + binary(json value)
JSON과 비슷한 형식이지만, 스키마가 존재합니다. 아래는 avro를 통해 데이터를 표시한 예입니다.
// user.avsc { "type": "record", "name": "LongList", "aliases": ["LinkedLongs"], // old name for this "fields" : [ {"name": "value", "type": "long"}, // each element has a long {"name": "next", "type": ["null", "LongList"]} // optional next element ] }
JSON
복사
예시 avro 코드 (python)
카프카에서는 일관적인 데이터 형식이 중요합니다. 읽기 작업과 쓰기 작업이 분리되어 있기에 잘 정의되어 있는 스키마를 공유 저장소에 저장하여 동시에 지원하는 작업을 수행하는 것을 권장합니다.
1.2.3 토픽과 파티션
카프카에 저장되는 메시지는 토픽단위로 분류됩니다. 이러한 토픽은 다시 여러 개의 파티션으로 나뉘어집니다.
커밋 로그의 관점에서는 파티션은 하나의 로그에 해당됩니다. 파티션에 메시지가 쓰여질 때는 추가만 가능한 형태로 쓰여지며, FIFO로 읽힙니다.
토픽에 여러개의 파티션이 있는 만큼 토픽 안의 메시지 전체에 대해 순서는 보장되지 않으며, 단일 파티션 안에서의 메시지만 순서가 보장됩니다.
9, 10, 11, 12의 메시지가 다른 파티션에 저장되며, 단일 파티션에 대한 메시지는 순서가 보장됩니다.
각 파티션이 서로 다른 서버에 저장될 수 있기 때문에 하나의 토픽이 여러 개의 서버로 투평적으로 확장되어 하나의 서버의 용량을 넘어가는 성능을 보여줄 수 있습니다.
또한 파티션은 복제될 수 있습니다. 즉, 서로 다른 서버들이 동일한 파티션의 복제본을 저장하고 있기 때문에 서버 중 하나에 장애가 발생한다고 해서 읽거나 쓸 수 없는 상황은 일어나지 않습니다.
1.2.4 프로듀서와 컨슈머
프로듀서
프로듀서는 새로운 메시지를 생성합니다. PublisherWriter라고도 부릅니다. 메시지는 특정한 토픽에 쓰여집니다.
기본적으로 메시지를 쓸 때 토픽에 속한 파티션을 나눠서 쓰도록 되어 있습니다. 대게 키와 키값의 해시를 통해 특정 파티션을 대응시키는 파티셔너를 사용하여 구현됩니다. 동일한 키값을 가진 메시지는 같은 파티션에 저장되게 됩니다. (커스텀 파티셔너도 지정 가능)
컨슈머
컨슈머는 메시지를 읽습니다. 1개 이상의 토픽을 구독하여 저장된 메시지들을 각 파티션에 쓰여진 순서대로 읽어 옵니다. 메시지에 오프셋을 기록함으로써 어느 메시지까지 읽었는지를 유지합니다.
컨슈머 그룹
컨슈머는 컨슈머 그룹의 일원으로써 작동합니다. 토픽에 저장된 데이터를 읽어오기 위해 협업하는 하나 이상의 컨슈머로 이루어집니다.
따라서 2개이상의 클러스터를 통해 컨슈머를 분리하여도 메시지의 순서가 유지될 수 있습니다.
하나의 컨슈머가 2개이상의 파티션을 읽을 수 있는데 이러한 대응 관계를 컨슈머의 파티션 소유권이라고 합니다.
위의 방법을 사용함으로써 대량의 메시지를 갖는 토픽들을 읽기 위해 컨슈머들을 수평 확장할 수 있습니다. 컨슈머 중 하나에 장애가 발생하더라도, 그룹 안의 다른 컨슈머들이 파티션을 재할당 받아 다시 일합니다.
1.2.5 브로커와 클러스터
하나의 카프카 서버를 브로커 라고 부릅니다. 브로커는 프로듀서로부터 메시지를 전달받아 오프셋을 할당한 뒤 디스크 저장소에 작성합니다.
카프카의 브로커는 클러스터의 일부로써 작동하도록 설계되었습니다. 하나의 클러스터 안에 여러 개의 브로커가 포함될 수 있으며, 그 중 하나의 브로커가 클러스터 컨트롤러의 역할을 하게 됩니다. (slave - master 느낌과 비슷한 듯?)
컨트롤러는 파티션을 브로커에 할당해주거나 브로커를 모니터링하는 관리 기능을 담당합니다.
파티션은 클러스터 안의 브로커 중 하나가 담당하며 이를 파티션 리더라고 합니다.
복제된 파티션은 여러 브로커에 할당될 수도 있는데 이들을 파티션의 팔로워라고 합니다.
복제 기능은 파티션의 메시지를 중복 저장함으로써 리더 브로커에 장애가 발생했을 때 팔로워 중 하나가 리더 역할을 이어할 수 있도록 합니다.
아파치 카프카의 핵심 기능 중 하나로 메시지를 지속성있게 보관하는 보존 기능이 있습니다.
특정 기간동안 메시지를 보존하거나 파티션의 크기가 특정 사이즈에 도달할 때 까지 데이터를 보존합니다. 이러한 한도값에 도달하면 메시지는 만료되어 삭제됩니다.
각각의 토픽에는 메시지가 필요한 정도까지만 저장되도록 보존 설정을할 수 있습니다. 예를 들어 사용자 활동 추적 토픽은 며칠 동안 유지할 수 있는 반면, 어플리케이션 지표는 겨우 몇 시간만 보존할 수 있습니다.
1.2.6 다중 클러스터
카프카의 확장에 따라 다수의 클러스터를 운용할 수 있습니다.
데이터 유형별 분리
보안 요구사항을 충족시키기 위한 격리
재해 복구를 대비한 다중 데이터센터
카프카가 다수의 데이터센터에서 운용될 때는 데이터센터 간에 메시지를 복제해 줄 필요가 있는 경우가 있습니다. 예를 들어 자신의 프로필에 있는 공개 정보를 수정한다면 변경사항은 데이터센터가 위치 여부와 상관없이 노출되어야 합니다.
카프카의 클러스터 복제 메커니즘은 다중 클러스터 사이에서가 아닌 하나의 클러스터 안에서만 작동하도록 설계되었습니다.
카프카 프로젝트는 미러케이커라는 툴을 제공합니다. 이는 다른 데이터센터(클러스터)의 메시지를 읽어와 또 다른 데이터센터로 복사하는 기능을 수행합니다.

Why Kafka?

발행/구독 메시지 전달 시스템중에 왜 카프카를 사용할까?
1.3.1 다중 프로듀서 제공
카프카는 여러 프로듀서를 처리할 수 있습니다. 프로듀서가 여러 토픽을 사용하든 하나의 토픽을 사용하든 간에 말입니다. 이는 MSA환경에서 일관성있게 데이터를 유지하는데 적합합니다.
1.3.2 다중 컨슈머 제공
카프카는 많은 컨슈머가 상호 간섭 없이 어떠한 메시지 스트림도 읽을 수 있도록 설계되었습니다. 다수의 컨슈머는 컨슈머 그룹의 일원으로 작동함으로써 하나의 스트림을 여럿이서 나눠서 읽을 수 있습니다. (주어진 메시지는 전체 컨슈머 그룹에 대해 한 번만 처리됩니다.)
1.3.3 디스크 기반 보존
카프카는 메시지를 지속성 있게 저장할 수 있습니다. 이는 컨슈머가 데이터를 실시간으로 읽어올 필요는 없다는 의미기도 합니다. 컨슈머가 정지하더라도 메시지는 카프카 내부에 보존됩니다.
1.3.4 확장성
카프카는 유연한 확장성을 가지고 있기 때문에 어떻나 크기의 데이터도 쉽게 처리할 수 있습니다. 하나의 브로커에서 수십개의 브로커로 구성된 환경으로의 이동이 가능합니다.
1.3.6 플랫폼 기능
다양한 API와 라이브러리의 형태를 제공합니다.

1.4 데이터 생태계

카프카는 모든 클라이언트에 대해 일관된 인터페이스를 제공하면서 다양한 인프라 요소들 사이에 메시지를 전달하는 것이 가능합니다.
1.4.1 이용 사례
활동 추적
1.
메시지 교환
다양한 환경에서의 메일 API 호출을 동일한 형식, 일정하게 호출 가능합니다.
2.
지표 및 로그 수집
3.
커밋 로그
데이터베이스에 가해진 커밋로그가 카프카로 발행됨으로써 쉽게 실시간 업데이트를 받아볼 수 있습니다.
로그 압착기능을 사용함으로써 DB의 이용을 줄일 수 있습니다.
로그 압착 기능 : 토픽에 키별로 마지막 값 하나만을 보존
4.
스트림 처리

1.5 카프카의 기원

과거 링크드인의 모니터링 시스템에는 많은 결함이 있었습니다.
폴링 방식으로 수집되는 지표들이 있었는데, 지표가 수집되는 간격이 긴 데다가 지표를 관리하는데 손이 많이가 불편함이 있었습니다.
1.5.2 카프카의 탄생
이들은 다음과 같은 요구사항을 만족시키는 카프카를 만들게 됩니다.
푸시-풀 모델을 사용함으로써 프로듀서와 컨슈머를 분리
다수의 컨슈머가 사용할 수 있도록 메시지 교환 시스템의 데이터를 영속적으로 저장
높은 메시지 처리량을 보일 수 있도록 최적화
데이터 스트림의 양이 증가함에 따라 시스템의 수평적 확장 제공