본문 바로가기
G.Code/kafka

[kafka] 3.카프카 기본개념 설명

by 한선배 2021. 11. 4.
반응형

브로커 역할


  • 카프카는 메모리나 데이터베이스에 저장하지 않으며 따로 캐시메모리를 구현하여 사용하지 않는다. 파일시스템에 데이터를 저장해서 속도가 떨어질거라는 의문을 가질수도 있지만 카프카는 페이지캐쉬(page cache)를 사용하여 입출력 속도를 높였다.
  • 페이지 캐쉬란?
    OS에서 파일 입출력의 성능 향상을 위해 만들어 놓은 메모리 영역
  • 카프카 브로커란?
    카프카 클라이언트와 데이터를 주고받기 위해 사용하는 주체이자, 데이터를 분산 저장하여 장애가 발생하더라도 안전하게 사용할 수 있도록 도와주는 애플리케이션
  • 컨트롤러란?
    다른 브로커들의 상태를 체크하고 브로커가 클러스터에서 빠지는 경우 해당 브로커에 존재하는 리더 파티션을 분배 한다. 컨트롤러 역할을 하는 브로커에 장애가 생기면 다른 브로커가 컨트롤러 역할을 한다.
  • 데이터 삭제
    프로듀서나 컨슈머가 토픽의 데이터를 삭제 할 수 없다.(오직 브로커만 데이터 삭제가 가능) 데이터 삭제는 파일 단위로 이루어지는데 이 단위를 로그 세그먼트(log segment)라고 한다. 카프라 브로커에 log.segement.bytes 또는 log.segment.ms 옵션에 값이 설정되면 세그먼트 파일이 닫힌다. 닫힌 세그먼트 파일은 log.retention.bytes 또는 log.retention.ms 옵션에 설정값이 넘으면 삭제가 된다.
  • 코디네이터(coordinator)
    클러스터의 다수 브로커 중 한대는 코디네이터 역할을 수행한다. 코디네이터는 컨슈머 그룹의 상태를 체크하고 파티션을 컨슈머와 매칭되도록 분배하는 역할을 한다.

주키퍼 역할


  • 주키퍼란?
    카프카의 메타데이터를 관리하는데 사용한다. 주키퍼 쉘은 bin/zookeeper-shell.sh로 실행 할 수 있다.
    $ bin/zookeeper-shell.sh my-kafka:2181
    쉘 수행시 브로커 내 컨트롤러, 토픽, 네트워크 정보 등을 확인 할 수 있다.

토픽과 파티션


  • 토픽이란?
    카프카에서 데이터를 구분하기 위해 사용하는 단위이다. 토픽은 1개 이상의 파티션을 소유하고 있다. 파티션에는 프로듀서가 보낸 데이터들이 들어가 있는데 이 데이터를 '레코드(record)'라고 부른다. 파티션은 카프카의 병렬처리의 핵심으로써 그룹으로 묶인 컨슈머들이 레코드를 병렬로 처리 할 수 있도록 매칭된다. 처리량에 따라 파티션과 컨슈머는 스케일 인 & 아웃이 된다.

레코드


  • 레코드란?
    레코드는 타임스탬프, 메시지 키, 메시지 값, 오프셋, 헤더로 구성되어 있다. 프로듀서가 생성한 레코드가 브로커로 전송되면 오프셋과 타임스탬프가 지정되어 저장된다. 브로커에 한번 적재된 레코드는 수정할 수 없고 로그 리텐션 기간 또는 용량에 따라서만 삭제 된다.

카프카 클라이언트


  • 카프라 클라이언트란?
    카프카 클러스터에 명령을 내리거나 데이터를 송수신 하기 위해 카프카 클라이언트 라이브러리는 프로듀서, 컨슈머, 어드민 클라이언트를 제공하는 카프카 클라이언트를 사용하여 어플리케이션을 개발한다.
  • 프로듀서 API란?
    카프카의 시작점을 프로듀서이다. 프로듀서 애플리케이션은 카프카에 필요한 데이터를 선언하고 브로커의 특정 토픽의 파티션을 전송한다. 프로듀서는 데이터를 전송할 때 리더 파티션을 가지고 있는 카프카와 직접 통신한다.
  • 프로듀서 중요개념
    프로듀서는 카프카 브로커로 데이터를 전송할때 내부적으로 파티셔너, 배치 생성 단계를 거친다.
    ProducerRecord 클래스를 통해서 메세지 인스턴트를 생성 한다. KafkaProducer 인스턴스가 send() 메서드를 호출하면 ProducerRecord는 파티셔너에서 토픽이 어느 파티션으로 전송될 것인지 정해진다. 파티셔너에 구분된 레코드는 데이터를 전송하기 전에 어큐뮬레이터에 데이터를 버퍼로 쌓아놓고 발송한다. 버퍼로 쌓인 데이터는 배치로 묶어서 전송함으로써 카프카의 프로듀서 처리량을 향상시키는 데에 상당한 도움을 준다.
    프로듀서 API를 사용하면 'UniformStickyPartitioner'와 'RoundRobinPartitioner' 2개 파티션을 제공한다. 2.5.0 버전에서는 파티셔너를 지정하지 않으면 'UniformStickyPartitioner' 기본으로 설정 된다.
    UniformStickyPartitioner : 프로듀서 동작에 특화되어 높은 처리량과 낮은 리소스 사용률을 가지는 특징이 있다. 에큐물레이터에서 데이터가 배치로 모두 묶일때까지 기다렸다가 배치로 묶인 데이터는 모두 동일한 파티션에 전송함
    2.4.0 버전부터 UniformStickyPartitioner 가 기본 파티셔너로 지정 되었다.
    RoundRobinPartitioner : ProducerRecord가 들어오는 대로 파티션을 순회하면서 전송한다. 그래서 배치로 묶인 빈도가 적다. 성능이 떨어짐
    센더(sender) 스레드 : 어큐뮬레이터에 쌓인 배치 데이터를 가져가 카프카 브로커로 전송한다.
    추가적으로 카프카 프로듀서는 압축 옵션을 사용하여 브로커에 전송을 할 수가 있다.(gzip, snappy, lz4, zstd 지원) 압축을 하면 데이터 전송 시 네트워크 처리량에 이득을 볼 수 있지만 CPU, 메모리 리소스를 사용하므로 사용환경에 따라 적절한 옵션을 사용하는 것이 중요하다.

프로듀서 애플리케이션 실행
프로듀서 소스 코드

  • 프로듀서 주요 옵션
    - 필수 옵션 : 필수로 입력해야 하는 옵션
      bootstrap.servers : 카프카 클러스터에 속한 브로커 호스트이름:포트를 1개 이상 작성한다. 2개 이상 브로커의 정보도 입력 가능하다.
      key.serializer : 레코드의 메시지 키를 직렬화하는 클래스 지정
      value.serializer :  레코드의 메시지 값을 직렬화하는 클래스 지정
    - 선택 옵션 : 필수로 입력하지 않아도 되는 옵션(중요하지 않은것은 아님)
    acks : 프로듀서가 전송한 데이터가 브로커들에 정상적으로 저장되었는지 전송 성공여부를 확인하는데 사용한다.(1,0,-1) 기본은 1이다. 1은 리더 파티션에 저장되면 전송 정상, 0은 전송한 즉시 브로커에 데이터 저장 여부와 상관없이 성공으로 판다. -1 또는 all은 리더 파티션과 팔로워 파티션에 데이터가 저장되면 성공으로 간주
    buffer.memory : 브로커로 전송할 데이터를 배치로 모으기 위해 설정할 버퍼 메모리양 지정. 기본 32MB
    retries : 프로듀서가 브로커로부터 에러를 받고 난 뒤 재전송을 시도하는 횟수를 저정한다. 기본 2147483648
    batch.size : 배치로 전송할 레코드의 최대 용량을 지정
    linger.ms : 배치를 전송하기 전까지 기다리는 최소 시간. 기본 0
    partitioner.class : 레코드를 파티션에 전송할 때 적용하는 파티셔너 클래스 기본 : org.apache.kafka.clients.producer.internals.DefaultPartitioner
    enable.idempotence : 멱등성 프로듀서로 동작할지 여부 설정
    transactional.id : 프로듀서가 레코드를 전송할 때 레코드를 트랜잭션 단위로 묶을지 여부를 설정
  • 컨슈머 중요 개념
    컨슈머 운영방법 : 1개 이상의 컨슈머로 이루어진 컨슈머 그룹을 운영, 토픽의 특정 파티션만 구독하는 컨슈머를 운영
  • 어드민 API

카프카 클라이언트에서는 내부 옵션들을 설정하거나 조회하기 위해 AdminClient 클래스를 제공한다. AdminClient 클래스를 활용하면 클러스터의 옵션과 관련된 부분을 자동화할 수 있다.

KafkaAdminClient 메서드명 설명
describeCluster(DescribeClusterOptions options) 브로커의 정보조회
listTopics(ListTopicsOptions options) 토픽 리스트 조회
listConsumerGroups(ListConsumerGroupsOptions options) 컨슈머 그룹 조회
creatTopics(Collection <NewTopic> new Topics, CreateTopicOptions options) 신규 토픽 생성
createPartitions(Map <String,NewPartitions> new Partitions, CreatePartitionsOptions options) 파티션 개수 변겨
createAcls(Collection <AclBinding> acls, CreateAclsOptions options) 접근 제어 규칙 생성

카프카 스트림즈


  • 카프카 스트림즈란?
    카프카 스트림즈는 토픽에 적재된 데이터를 상태기반(Stateful) 또는 비상태기반(Stateless)으로 실시간 변환하여 다른 토픽에 적재하는 라이브러리이다.
    스트림즈 애플리케이션은 내부적으로 스레드를 1개 이상 생성할 수 있으며, 스레드는 1개 이상의 태스크를 가진다. 스트림즈의 '태스크'는 스트림즈 애플리케이션을 실행하면 생기는 데이터 처리 최소 단위 이다. 만약 3개의 파티션으로 이루어진 토픽을 처리하는 스트림즈 애플리케이션을 실행하면 내부에 3개의 태스크가 생성 된다.
  • 카프카 스트림즈를 사용해야 하는 이유?
    스트림즈는 카프카에서 공식적으로 지원하는 라이브러리이다. 매번 카프카 버전이 오를 때마다 스트림즈 자바 라이브러리도 같이 릴리즈 된다. 그렇기 때문에 자바 기반 스트림즈 애플리케이션은 카프카 클러스터와 완벽하게 호환되면서 스트림 처리에 필요한 편리한 기능들(신규 토픽 생성, 상태 저장, 데이터 조인 등)을 제공 한다.
  • 카프카 토폴로지
    토폴로지란 2개 이상의 노드들과 선으로 이루어진 집합을 뜻한다. 토폴로지의 종류로는 링형, 트리형, 성형 등이 있는데 스트림즈에서 사용하는 토폴로지는 트리 형태와 유사하다.
    카프카 스트림즈에서는 토폴로지를 이루는 노드를 하나의 '프로세서'라고 부르고 노드와 노드를 이은 선을 '스트림'이라고 부른다. 스트림은 토픽의 데이터를 뜻하는데 프로듀서와 컨슈머에서 활용했던 레코드와 동일하다. 프로세서에는 소스 프로세서, 스트림 프로세서, 싱크 프로세서 3가지가 있다. 
    소스프로세서 : 데이터를 처리하기 위해 최초로 선언해야 하는 노드, 하나의 토픽에서 데이터를 가져오는 역할을 한다.
    스트림 프로세서 : 다른 프로세서가 반환한 데이터를 처리하는 역할을 한다. 변환, 분기처리와 같은 로직이 데이터 처리의 일종이라고 볼 수 있다. 
    싱크 프로세서 : 데이터를 특정 카프카 토픽으로 저장하는 역할을 하며 스트림즈로 처리된 데이터의 최종 종착지이다.
    스트림즈DSL(Domain Specific Language)과 프로세서 API 2가지 방법으로 개발 가능하다.
    o 스트림즈DSL로 구현하는 데이터 처리 예시
     - 메시지 값을 기반으로 토픽 분기처리
     - 지난 10분간 들어온 데이터의 개수 집계
     - 토픽과 다른 토픽의 결합으로 새로운 데이터 생성
    o 프로세서 API로 구현하는 데이터 처리 예시
     - 메시지 값의 종류에 따라 토픽을 가변적으로 전송
     - 일정한 시간 간격으로 데이터 처리
  • 스트림즈DSL
    KStream : 레코드의 흐름을 표현헌 것으로 메세지 키와 메세지 값으로 구성되어 있다. KStream으로 데이터를 조회하면 토픽에 존재하는 모든 레코드가 출력 된다. 컨슈머로 토픽을 구독하는 것과 동일 선상에서 사용하는 것이라고 볼 수 있다.
    KTable : KTable은 KStream과 다르게 메시지 키를 기준으로 묶어서 사용한다. KStream은 토픽의 모든 레코드를 조회 할 수 있지만 KTable은 유니크한 메시지 키를 기준으로 가장 최신 레코드를 사용한다. 그러므로 KTable로 데이터를 조회하면 메시지 키를 기준으로 가장 최신에 추가된 레코드의 데이터가 출력된다. 새로 데이터를 적재할 때 동일한 메시지 키가 잇을 경우 데이터가 업데이트 되었다고 볼 수 있다. 왜냐하면 메시지 키의 가장 최신 레코드가 추가되었기 때문이다.
    GlobalTable : KTable과 동일하게 메시지 키를 기준으로 묶어서 사용된다. 그러나 KTable로 선언된 토픽은 1개 파티션이 1개 태스크에 할당되어 사용되고, GlobalTable로 선언된 토픽은 모든 파티션 데이터가 각 태스크에 할당되어 사용된다는 차이점이 있다.
  • 스트림즈DSL 필수 옵션
    bootstrap.servers : 프로듀서가 데이터를 전송할 대상 카프카 클러스터에 속한 브로커의 호스트 이름:포트 1개 이상 작성한다.
    application.id: 스트림즈 애플리케이션을 구분하기 위한 고유한 아이디를 설정한다. 다른 로직을 가진 스트림즈 애플리케이션들은 서로 다른 application.id를 가져야 한다.
  • 스트림즈DSL - stream(). to()
    특정 토픽을 KStream형태로 가져오려면 스트림즈DSL의 stream() 메서드를 사용하면 된다. KStream의 데이터를 특정 토픽으로 저장하려면 스트림즈DSL의 to() 메서드를 사용한다.

카프카 커넥트


  • 카프카 커넥트(kafka connect)란?
    카프카 오픈소스에 포함된 툴 중 하나로 데이터 파이프라인 생성 시 반복 작업을 줄이고 효율적인 전송을 이루기 위한 애플리케이션이다. 파이프라인을 생성할 때 프로듀서, 컨슈머 애플리케이션을 만드는 것은 좋은 방법이지만 반복적인 파이프라인 생성 작업이 있을 때는 매번 프로듀서, 컨슈머 애플리케이션을 개발하고 배포, 운영해야 하기 때문에 비효율적이다. 반면, 커넥트는 특정한 작업 형태를 템플릿으로 만들어놓은 커넥터(connector)를 실행함으로써 반복 작업을 줄일 수 있다.(토픽 이름, 파일 이름, 테이블 이름 등을 파라미터로 받는 커넥터 코드 작성)
    커넥터는 프로듀서 역할을 하는 '소스 커넥터'와 컨슈머 역할을 하는 '싱크 커넥터' 2가지 나뉜다. 
  • 커넥트를 실행하는 방법
    - 단일 모드 커넥트 : 단일 어플리케이션에서 실행. 커넥터를 정의하는 파일을 작성하고 해당 파일을 참조하는 단일모드 커넥트를 실행함으로써 파이프라인을 생성 할 수 있다. 단일 프로세스로 실행되기 때문에 고가용성 구성이 되지 않아 단일 장애점(SPOF)이 될 수 있다.
    - 분산 모드 커넥트 : 2대 이상의 서버에서 클러스터 형태로 운영. 단일 모드 커넥트에 비해 안전하게 운영 할 수 있다는 장점이 있다. 또한 데이터 처리량의 변화에도 유연하게 대응할 수 있다.(스케일 아웃 가능)

    REST API를 사용하면 현재 실행 중인 커넥트의 커넥터 플러그인 종류, 태스크 상태, 커넥터 상태 등으르 조회할 수 있다. 커넥트는 8083 포트로 호출할 수 있으며 HTTP 메서드(GET, POST, DELETE, PUT) 기반 API를 제공한다. 
  • 소스 커넥터란?
    - 소스 커넥터는 소스 애플리케이션 또는 소스 파일로부터 데이터를 가져와 토픽으로 넣는 역할을 한다. 소스커넥트를 만들 떄 필요한 클래스는 2개다. 첫번째는 SourceConnector이고 SourceTask이다. SourceConnector는 태스크를 실행하기 전 커넥터 설정파일을 초기화하고 어떤 태스크 클래스를 사용할 것인지 정의하는 데 사용한다. 그렇기 때문에 SourceConnector에는 실질적인 데이터를 다루는 부분이 들어가지 않는다. SourceTask는 실제로 데이터를 다루는 클래스라고 볼 수 있다. SourceTask는 소스 애플리케이션 또는 소스 파일로부터 데이터를 가져와서 토픽으로 데이터를 보내는 역할을 수행한다.
  • 싱크 커넥터란?
    - 싱크 커넥터는 토픽의 데이터를 타킷 애플리케이션 또는 타깃 파일로 저장하는 역할을 한다. 싱크 커넥터를 만들때 필요한 클래서는 2개다. 첫 번째는 SinkConnector이고 두 번째는 SinkTask 이다. SinkConnector는 태스크를 실행하기 전에 사용자로부터 입력받은 설정값을 초기화하고 어떤 태스크 클래스를 사용할 것인지 정의하는 데에 사용한다. 실제로 데이터를 처리하는 로직은 SinkTask로 구현한다. SinkTask가 커넥트에서 컨슈머 역할을 하고 데이터를 저장하는 코드를 가지게 된다.

 

 

반응형