kafka 이해(번역)
다음 글에서 이어지는 내용
2019/02/13 - [프로그래밍/아키텍쳐] - 메세지큐와 AMQP
아래의 내용은 kafka 공식홈의 intro를 번역/요약함
※ 주의
주관적인 해석과 순서가 뒤에서부터 해석하는 번역체같은 느낌이 나올 수 있으니 참고하시길 바랍니다.
kafka
kafka는 Linked In에서 2011년에 오픈소스로 개발된 분산 메시징 시스템이다. 대용량 실시간 로그처리에 특화되어있고 많은 회사들이 사용하는 제품이기도 하다. 요즘처럼 하루에 최소 GByte에서 많게는 T~PByte까지 데이터가 발생하는 세상에서는 필수적이라고 할 수 있다.
개념
kafka(이하 카프카)는 분산 스트리밍 플랫폼(Distributed Streaming Platform)이다.
스트리밍 플랫폼의 3가지 능력(특징)
- 엔터프라이즈 메세징 시스템이나 메세지큐와 유사하게 records(레코드)의 stream(스트림)을 Publish(게시) & Sunscribe(구독)한다.
- 레코드의 스트림을 fault-tolerant(장애 감내) 방식으로 튼튼하게 저장한다.
- 레코드가 발생하면 해당 스트림을 처리한다.
정리하면 카프카는 하나의 메세지큐로 발행-구독 모델 방식을 사용하고 레코드가 발생하면 바로 처리하며 장애 감내 방식으로 자료의 손실을 방지한다.
주요 사용처
- 시스템 또는 애플리케이션 사이의 데이터를 안전하게 사용할 수 있도록 실시간 데이터 파이프라인 스트리밍 구축
- 데이터의 스트림을 바꾸거나 반응하기 위한 실시간 애플리케이션 스트리밍 구축
주요 개념
- 카프카는 여러 데이터 센터로 확장될 수 있는 하나 이상의 서버에서 클러스터로 동작한다.
- 카프카 클러스터는 topics(토픽)으로 불리는 카테로리에 레코드의 스트림을 저장한다.
- 자료는 key, value, timestamp로 구성되어 있다.
- 카프카에서 클라이언트와 서버 간의 통신은 단순하고 성능 좋고 언어와 상관없는(language agnostic) TCP 프로토콜을 사용한다.
(agnostic이 "신의 존재 여부를 안다고 확신하지 않는다."는 뉘앙스로 쓰이는데 language agnostic 으로 쓰이니 언어에 구애받지 않는다로 번역이 되더라...)
주요 API
- Producer API : 애플리케이션이 하나 이상의 토픽에 레코드의 스트림을 게시하도록 허용함.
- Consumer API : 애플리케이션이 하나 이상의 토픽에 구독하고 생산된 레코드의 스트림을 처리하도록 허용함.
- Streams API : 애플리케이션이 하나 이상의 토픽으로 부터 입력 스트림을 소비하고 하나 이상의 출력 토픽으로 출력 스트림을 생성하여 효과적으로 입력 스트림을 출력 스트림으로 변환한다.
- Connector API : 토픽을 기존 애플리케이션이나 데이터 시스템에 연결하는 재사용 가능한 producers, consumers을 만들어서 실행할 수 있다. 예로 관계형 DB의 커넥터는 테이블에 대한 모든 변경 사항을 캡처 할 수 있다.
토픽(Topic) & Logs
토픽은 게시된 레코드의 카테고리나 피드 네임(feed name)이다. 토픽은 항상 다중 구독(multi-subscriber)이다. 그 말은, 하나의 토픽에서 최소 0에서 다수의 consumer를 보유할 수 있다는 것이다. 아래의 그림처럼, 각 토픽에 대해서 카프카 클러스터는 파티션된 로그를 관리한다.
각 파티션은 순서가 지정되고 불변의 레코드 시퀀스(순서)는 끊임없이 추가(appended) 된다.(-구조화된 commit log로 추가된다.) 파티션의 레코드는 오프셋(offset)으로 불리는 id 넘버로 순서대로 부여된다. 오프셋은 파티션 내에서 각 레코드를 구별하기 위한 유니크한 식별자다.
카프카 클러스터는 모든 게시된 레코드를 소비(consumed)하든 안하든 영원히 보존한다. 그리고 설정 가능한 보존 기간(configurable retention period)을 사용한다. 예를 들어서 보존 정책을 2일로 정하면 레코드가 게시된 후 2일 동안 소비 가능하다. 그 후에는 공간을 비우기 위해 폐기된다. 카프카 성능은 데이터를 오랫동안 저장하는 것에 대해서 문제가 되지 않는다.(데이터 크기가 실질적으로 일정하므로)
사실은 소비자당 유지되는 메타데이터는 소비자의 오프셋이나 위치(position)이다. 이 오프셋은 소비자에 의해 컨트롤되며, 보통 소비자는 레코드를 읽을때 오프셋을 하나씩 당겨가며 읽을 것이다. 하지만 사실 위치는 소비자에 의해 제어되기 때문에 좋아하는 순서대로 소비할 수 있다. 예를 들어서 소비자가 데이터를 재처리하기 위해서 오래된 오프셋을 리셋할 수 있다.(과거나 생략된 데이터를 재처리하거나 최근 레코드를 건너 뛰고 당장(now) 들어온 데이터를 소비할 수 있다.)
이런 기능의 결합은 카프카 소비자가 매우 저렴(cheap)하다는 것을 의미한다. 저렴하다란 카프카 클러스터나 다른 소비자들에게 큰 영향을 미치지 않고 오락가락(come and go)할 수 있다는 것이다. 예를 들어, 기존 소비자가 소비하는 것을 변경하지 않고 어떤 토픽의 컨텐츠의 "tail" 명령어를 사용할 수 있다.
로그의 파티션은 여러가지 용도로 사용된다. 용도는 아래와 같다.
- 로그를 단일 서버에 맞는 크기 이상으로 확장할 수 있다.
(각 개별 파티션은 호스트하는 서버에 적합해야하지만, 토픽에는 많은 파티션이 있어 임의의 양의 데이터를 처리할 수 있다.) - 병렬 처리 단위로 작동한다.
분산(Distribution)
(2개의 서버를 클러스터로 묶고 3개의 파티션으로 나눈 카프카)
로그의 파티션은 카프카 클러스터의 서버를 통해 분산되며 각 서버는 데이터를 처리하고 파티션 공유에 대한 요청을 처리한다. 각 파티션은 장애 허용을 위해 설정 가능한 수의 서버에 복제된다. 각 파티션에는 리더(leader)역할 을 하는 0 이상의 서버가 있다. 리더는 팔로워(follower)가 리더를 수동적으로 복제하는 동안 파티션에 대한 모든 읽기/쓰기 요청을 처리한다. 리더가 실패하면 팔로워 중 하나가 자동으로 새로운 리더가 된다. 각 서버는 일부 파티션의 리더와 다른 서버의 팔로어로 작동하므로 부하(load)가 클러스터 내에서 균형을 이룹니다.
지역 복제(Geo-Replication)
(서울에 있는 클러스터의 데이터를 US, Japan에 복제)
카프카의 미러메이커(MirrorMaker)는 지역 복제를 제공해준다. 미러메이커란 여러 데이터 센터나 클라우드에 메세지를 복제해주는 것이다. 이것을 통해 active/passive한 백업 및 복구를 사용할 수 있다. 또한 데이터를 사용자 가까이에 배치하거나 데이터 지역성(Data locality) 지원하기 위해서 지원하는 경우에도 사용할 수 있다. 즉, 미러메이커는 장애조치 기능과 고가용성을 확보할 수 있는 기능이다.
생산자(Producers)
생산자는 선택한 토픽에 데이터를 게시한다. 생산자는 토픽 내에서 파티션에 레코드를 할당하는 역할을 가진다. 이는 간단하게 균형을 맞추기 위해 라운드 로빈 방식(Round-robin)으로 수행되거나 어떤 의미(기준)를 가진 파티션 함수에 따라 수행된다.(레코드의 일부 키를 기준으로 말한다) 두 번째로 파티셔닝을 더 많이 사용한다.
소비자(Consumers)
소비자는 소비자 그룹 이름으로 자신을 표시하고 토픽에 게시된 각 레코드는 구독 중인 소비자 그룹 내의 하나의 소비자 인스턴스에 전달(delivered)된다. 소비자 인스턴스는 여러 프로세스나 여러 기기가 될 수 있다.
만약 모든 소비자 인스턴스가 같은 소비자 그룹을 가진다면 레코드는 효과적으로 로드 밸런싱된다.
만약 모든 소비자 인스턴스가 다른 소비자 그룹을 가진다면 레코드는 모든 소비자 프로세스로 브로드캐스트(broadcast) 될 것이다.
(다른 소비자 그룹을 가져서 모든 소비자 그룹에 레코드가 브로드캐스트됨)
위의 그림을 예시를 들어보자. 2개의 서버로 구성된 카프카 클러스터에서 4개의 파티션을 호스팅 중이다. 그리고 2개의 소비자 그룹이 있고 소비자 A는 2개 소비자 B는 4개의 소비자 인스턴스를 보유하고 있다.
하지만 일반적으로 토픽이 더 적은 수의 소비자 그룹을 가지는걸 볼 수 있다. 그리고 그 중의 하나는 논리적인 구독자(logical subscriber)이다. 각 소비자 그룹은 확장성/결함허용(fault-tolerance)을 위해 많은 소비자 인스턴스로 구성된다. 이는 단일 프로세스 대신 소비자 클러스터로 구성된 구독자로 이뤄진 발행-구독 형태이다.
카프카에서 소비가 이뤄지는 방식 다음과 같다. 로그의 파티션을 소비자 인스턴스로 나눈다. 그러면 각 인스턴스가 어느 시점에서든 파티션의 "공정한 공유(fair share)"을 독점적으로 사용하는 것이다. 이 그룹의 멤버쉽을 유지하는 프로세스틑 카프카 프로토콜에 의해 동적으로 처리된다. 만약 새로운 인스턴스가 그룹에 추가되면 그룹의 다른 멤버로 부터 일부 파티션을 받는다. 만약 소비자 인스턴스가 죽으면 기존에 할당된 파티션은 나머지 인스턴스에 분산된다.
카프카는 토픽 내에서 파티션 내의 레코드에 대해서만 전체적인 순서를 제공한다.(다른 파티션 간에는 제공하지 않는다.) 파티션마다 순서를 합치는건 (대부분의 애플리케이션에 대해서) 키 단위로 데이터를 분할하는 기능으로 충분하다. 하지만 만약 전체적인 레코드의 순서가 필요하면 파티션이 하나뿐인 토픽에 대해서만 가능하다. 이것은 소비자 그룹당 단 하나의 소비자 프로세스를 의미한다.
멀티 테넌트(Multi-tenancy)
카프카는 멀티 테넌트 솔루션으로 배포(deploy)될 수 있다. 멀티 테넌트는 데이터를 생성하거나 소비할 수 있는 토픽을 설정하여 사용할 수 있다. 할당량(quotas)에 대한 운영지원도 있다. 관리자는 클라이언트에 의해 사용되는 브로커 리소스를 컨트롤하기 위한 요청의 할당량을 정의하거나 시행할 수 있다.
보장(Guarantees)
높은 수준의 카프카에서 다음을 보장한다.
- 생산자는 보내진 순서로 메세지를 각 토픽의 파티션에 추가한다. 즉, 만약 레코드 M1이 첫번째로 동일한 생산자에 의해 레코드 M2로 전송된다면 M1는 M2보다 낮은 오프셋을 가지고 로그에서 빨리 나타난다.
- 소비자 인스턴스는 로그 안에서 저장된 순서대로 레코드를 볼 수 있다.
- 복제 요소(replication factor)가 N개인 토픽에 대해서 로그에 커밋(committed)된 레코드를 잃지 않고 최대 N-1개의 서버 오류를 허용한다.
(이러한 자세한 보증에 대한 내용은 documentation 중 디자인 세션에 나와있다)
Kafka as a Messaging System
전통적인 엔터프라이즈 메세징 시스템과 카프카의 스트림 개념을 비교하면 어떨까?
메세징 시스템은 전통적으로 큐잉(queuing)과 게시-구독(publish-subscribe) 모델이 있다.
-
- 큐 모델 : 소비자의 풀(pool)은 서버에서 읽을 수 있으며 각 레코드는 그 중 하나에 저장된다.
- 장점 - 여러 소비자 인스턴스에 데이터를 나눠서 처리 가능하다. 그래서 처리 규모를 확장할 수 있다.
- 단점 - 대기열(queue)는 다중 구독자가 아니다. 하나의 프로세스가 데이터를 읽으면 사라진다.
- 큐 모델 : 소비자의 풀(pool)은 서버에서 읽을 수 있으며 각 레코드는 그 중 하나에 저장된다.
-
- 게시-구독 모델 : 레코드는 모든 소비자들에게 브로드캐스트된다.
- 장점 - 다중 프로세스에게 데이터를 브로드캐스트하는걸 허용한다.
- 단점 - 모든 메세지가 모든 구독자에게 간 뒤로는 프로세싱 스케일링 방법이 없다.
- 게시-구독 모델 : 레코드는 모든 소비자들에게 브로드캐스트된다.
소비자 그룹 개념은 일반적으로 2가지가 있다. 큐 모델처럼 프로세스 그룹을 통해 프로세스를 나누거나 게시-구독 모델처럼 카프카를 사용하면 여러 소비자 그룹에 메세지를 브로드 캐스트할 수 있다.
카프카 모델의 이점은 모든 토픽이 이러한 속성을 가지고 있다는 것이다. 즉, 프로세싱 규모를 조절할 수 있고 다중 구족자이기도하며 꼭 어떤 모델 하나를 선택할 필요가 없다는 것이다.
카프카는 전통적인 메세징 시스템보다 강력한 순서 보증(ordering guarantees)을 제공한다.
전통적인 큐는 서버에서 순서대로 레코드를 유지하고, 여러 소비자가 큐에서 소모하는 경우 서버는 저장된 순서대로 레코드를 전달한다. 하지만 서버가 순서대로 레코드를 전달하지만, 레코드는 소비자에게 비동기적으로 배달된다, 그래서 레코드는 아마도 다른 소비자들에게 순서대로 도착할 수 있다. 이 것은 사실상 병렬 소모(presence of parallel consumption)에서 레코드의 순서를 잃는다는 것을 의미한다. 메세지 시스템은 큐에서 하나의 프로세스만 사용할 수 있는 "독점적인 소비자(exclusive consumer)"라는 개념을 사용하여 문제를 해결하기도 하지만 처리과정에서 병렬 처리가 없다는 것을 의미한다.
카프카는 더 좋다. 병렬처리 개념-파티션-을 가짐으로써 토픽 내에서 카프카는 순서 보증과 소피자 프로세스에 대해 로드 밸런싱을 제공한다. 이 것은 토픽의 파티션을 소비자 그룹의 소비자에게 할당하여 각 파티션이 정확히 한 소비자에 의해 소비되도록 수행한다. 이렇게 하여 우리는 소비자가 해당 파티션의 유일한 독자임을 확인하고 순서대로 데이터를 소비한다. 파티션이 많으므로 많은 소비자 인스턴스에서 부하의 균형을 유지한다. 그러나 소비자 그룹에는 파티션보다 더 많은 소비자 인스턴스가 있을 수 없습니다.
Kafka as a Storage System
분리된 게시 중인 메세지를 사용하지 못하게 하는 메세지 큐는 사실상 in-flight 메세지를 위한 스토리지 시스템으로써 작동한다. 카프카와 다른 점은 그것이 매우 좋은 스토리지 시스템이라는 것이다.
카프카에 쓰여진 데이터는 디스크에 기록되거나 내결함성(fault-tolerance)을 위해 복제된다. 카프카는 생산자가 승인을 기다릴 수 있게 하고 쓰기가 완료될 때까지 쓰기가 완료되지 않은 것으로 간주되어 서버가 실패한 경우에도 쓰기가 유지된다.
(Kafka allows producers to wait on acknowledgement so that a write isn't considered complete until it is fully replicated and guaranteed to persist even if the server written to fails. - 무슨 수능에서 나올법한 문장이었다;; so that, until, even if 로 split해서 해석하니 해석이 되더라...)
scale well-kafka를 사용하는 디스크 구조 - 카프카는 니가 서버에서 영구 데이터를 50KB든 50TB든 가지고 있어도 똑같이 처리 한다.
스토리지를 진지하게 받아들이고 클라이언트에게 read 포지션을 컨트롤할 수 있게 허락하는 것의 결과로써, 너는 특별한 목적으로써 카프카를 고성능, 낮은 커밋 로그 스토리지 응답속도, 복제 그리고 전달(propagation)의 분산 파일 시스템으로 생각할 수 있다.
커밋 로그 스토리지와 복제 디자인에 대한 자세한건 이 페이지를 읽어보자
Kafka for Stream Processing
이 것은 데이터의 스트림을 단순히 읽고 쓰고 저장하는 것에 충분하지 않다. 목적은 실시간 스트림 처리을 하기 위함이다.
카프카에서 스트림 프로세서는 입력된 토픽으로부터 연속된 데이터의 스트림을 받거나 입력에서 몇가지 프로세싱을 수행하거나 토픽으로 출력하기 위해 연속된 데이터의 스트림으로부터 생산할 수 있다.
예를 들어 소매 애플리케이션(retail application)은 아마도 판매와 배송의 스트림 입력을 받을 것이고 재주문과 이 데이터로 가격 조정된 가격의 스트림을 출력할 것이다.
이것은 생산자, 소비자 API을 사용함으로써 직접 간단하게 처리할 수 있다. 하지만 복잡한 변형의 경우 카프카는 완전히 통합된 stream API를 제공한다. 따라서 스트림에서 집계를 계산하거나 스트림을 함께 결합하는 중요하지 않은 처리를 하는 애플리케이션을 작성할 수 있다.
이 기능은 이러한 타입의 애플리케이션이 직면한 어려운 문제를 푼다 : 순서가 잘못된(out-of-order) 데이터를 다루거나 바뀐 코드로 입력을 재처리하거나 상태 계산을 수행한다.
스트림 API는 카프카가 제공하는 핵심 기본 요소를 기반으로 한다 : 입력에 생산자, 소비자 API를 사용하고 상태 저장을 위해 사용하고 스트림 프로세서 인스턴스 간의 내결함성을 위해 동일한 그룹 메커니즘을 사용한다.
조각맞추기(Putting the Pieces Together)
메세지, 스토리지 그리고 스트림 프로세싱의 결합은 드문 것처럼 보인다. 하지만 스트리밍 플랫폼으로써 카프카의 역할은 필수적이다.
HDFS와 같은 분산 파일 시스템을 배치 프로세싱을 위해 정적파일 저장할 수 있다. 사실상 이런 시스템은 과거의 역사적인 데이터를 저장하거나 처리할 수 있다.
전통적인 엔터프라이즈 메세징 시스템은 니가 구독한 뒤로 도착한 미래의 메세지를 처리하도록 한다. 애플리케이션은 도착하는 대로 미래의 데이터를 처리하도록 만들어진다.
카프카는 두가지 기능을 모두 결합하고 있고 이러한 기능은 스트리밍 데이터 파이프라인뿐 아니라 스트리밍 애플리케이션으로 카프카를 사용하는데 있어 중요하다.
스토리지와 낮은 구독 반응속도, 스트리밍 애플리케이션을 결합함으로써 과거와 미래의 데이터를 같은 방식으로 다룰 수 있다. 하나의 애플리케이션은 역사적이고 저장된 데이터를 처리할 수 있다기보단 마지막 레코드가 도달할 때 종료하지 않고 미래의 데이터가 도착할 때까지 처리를 유지할 수 있다. 이 것은 배치 프로세싱뿐만 아니라 메세지 드리븐(driven) 애플리케이션을 포함하여 스트림 프로세싱의 일반적인 개념이다.
마찬가지로 데이터 파이프라인 스트리밍의 경우 실시간 이벤트에 가입하면 매우 짧은 응답속도의 파이프 라인에 카프카를 사용할 수 있다. 그러나 안정적으로 데이터를 저장하는 능력은 중요한 데이터 전달을 보장해야하는 중요한 데이터 또는 주기적으로 데이터를 로드하는 오프라인 시스템과의 통합을 위해 사용하거나 유지 관리를 위해 오랜 기간 동안 중단될 수 있다. 스트림 프로세싱 시설은 도착하는 대로 데이터로 변환할 수 있게 한다.
~(한 문장에 263자... ㅂㄷㅂㄷ)~
카프카의 보증, API, 기능에 대한 정보는 다음 문서를 봐라
번역끝
이제 quick start 실습 전에 주키퍼에 대해 또 알아야한다.
2019/03/09 - [프로그래밍/아키텍쳐] - 주키퍼(ZooKeeper)