Kafka - Kafka Streams

bw1611·2023년 11월 24일
0

카프카 스트림즈란?


카프카 스트림즈는 토픽에 적재된 데이터를 상태기반(Stateful) 또는 비상태기반(stateless)으로 실시간 변환하여 달느 토픽에 적재하는 라이브러리이다.

  • 카프카의 스트림 데이터 처리를 위한 오픈소스 종류
    • 아파치 스파크
    • 아파치플링크
    • 아파치 스톰
    • 플루언티드

다양한 아파치 오픈소스 애플리케이션이 존재하지만 카프카 스트림즈를 사용해야하는 이유는 상당히 많다. 스트림즈는 카프카에서 공식적으로 지원하는 라이브러리이며, 매번 카프카 버전이 오를 때마다 스트림즈 자바 라이브러리도 같이 릴리즈가 되기 때문이다. 이런 이유로 카프카 클러스터와 완벽하게 호환되면서 스트림 처리에 필요한 편리한 기능들을 제공한다. 또한 장애가 발생하더라도 한번 할 수 있도록 장애 허용 시스템을 지원하기 때문에 데이터 처리 안전성이 뛰어나다.

스트림즈 DSL


스트림 프로세싱에 쓰일 만한 다양한 기능들을 자체 API로 만들어 놓았다. 그렇기 때문에 대부분의 변환 로직을 어렵지 않게 개발할 수 있다.

스트림즈 DSL의 3가지 개념

  • KStream
  • KTable
  • GlobalKTable

위의 3가지 개념은 컨슈머, 프로듀서, 프로세스 API에서 사용되지 않고 스트림즈 DSL에서만 사용되는 개념이다.

  • KStream

레코드의 흐름을 표현한 것으로 메시지 키와 메시지 값으로 구성되어 있다. KStream으로 데이터를 조회하면 토픽에 존재하는 모든 레코드가 출력된다. 컨슈머로 토픽을 구독하는 것과 동일 선상에서 사용하는 것이라고 볼 수 있다.

  • KTable

메시지 키를 기준으로 묶어서 사용한다. KStream은 토픽의 모든 레코드를 조회할 수 있지만 KTable은 유니크한 메시지 키를 기준으로 가장 최신 레코드를 사용한다. 새로 데이터를 적재할 때 동일한 메시지 키가 있을 경우 데이터가 업데이트되었다고 볼 수 있는데, 이유는 메시지 키의 가장 최신 레코드가 추가되었기 때문이다.

  • GlobalKTable

KTable과 동일하게 메시지 키를 기준으로 묶어서 사용한다. 하지만 KTable은 선언된 토픽은 1개 파티션 1개 Task에 할당되어 사용되지만, GlobalKTable로 선언된 토픽은 모든 파티션 데이터가 각 Task에 할당되어 사용된다는 차이점이 있다. KStream과 KTable을 조인하려면 반드시 코파티셔닝되어 있어야 한다. 이를 통해 각 태스크는 KStream의 레코드와 KTable의 메시지 키가 동일한 경우 조인을 수행한다.

코파티셔닝(co-partitioning) 이란?
조인을 하는 2개 데이터의 파티션 개수가 동일하고 파티셔닝 전략을 동일하게 맞추는 작업, 파티션 개수가 동일하고 파티셔닝 전략이 같을 경우에는 동일한 메시지 키를 가진 데이터가 동일한 태스크에 들어가는 것을 보장한다.

하지만 토픽들이 코파티셔닝되어 있음을 보장할 수 없기 때문에 조인을 수행하지 못하는 경우도 있다. 이럴 경우 리파티셔닝하는 과정을 거쳐야 하고 리파티셔닝 되는 과정 속에서 토픽에 기존 데이터를 중복해서 생성할 뿐만 아니라 파티션을 재배열하기 위해 프로세싱하는 과정도 거쳐야하기 때문에 번거로울 수 있다.
코파티셔닝되어 있지 않은 KStream과 데이터를 조인할 수 있는 GlobalKTable을 사용하는 것이 좋다. 하지만 단점으로는 모든 데이터를 저장하고 사용하기 때문에 스트림즈 애플리케이션의 로컬 스토리지의 사용량이 증가하고 네트워크, 브로커에 부하가 생기게 된다. 그러므로 많은 양을 데이터를 가진 토픽을 조인할 경우 리파티셔닝을 통해 KTable을 사용하는 것을 권장한다.

스트림즈 DSL - Stream(), to()


스트림즈 DSL로 구현할 수 있는 가장 간단한 스트림 프로세싱은 특정 토픽의 데이터를 다른 토픽으로 전달하는 것이다.
특정 토픽의 KStream 형태로 가져오려면 stream() 메서드를 사용하면 되고, KStream의 데이터를 특정 토픽으로 저장하려면 스트림즈 DSL의 to() 메서드를 사용하면 된다.

스트림즈 DSL - filter()


메시지 키 또는 메시지 값을 필터링하여 특정 조건에 맞는 데이터를 골라낼 때는 filter() 메서드를 사용하면 된다. filter 메서드는 스트림즈 DSL에서 사용 가능한 필터링 스트림 프로세서이다.

스트림즈 DSL - join()


  • Ktable과 KStream join()

KTable과 KStream은 메시지 키를 기준으로 조인할 수 있다. 대부분 DB는 정적으로 저장된 데이터를 조인하여 사용했지만 카프카에서는 실시간으로 들어오는 데이터들을 조인할 수 있다. KTable과 Kstream이 코파티셔닝되어 있지 않은 상태에서 join을 하게되면 TopologyException이 발생한다. 그러므로 토픽을 생성할 때 동일한 파티션 개수, 동일한 파티셔닝을 사용하는 것이 중요하다.

  • GlobalKTable과 KStream join()

코파티셔닝이 되어있지 않은 토픽을 조인해야 할 때는 GlobalKTable을 사용하는 것이 좋다.

프로세서 API


프로세서 API는 스트림즈 DSL보다 투박한 코드를 가지지만 토폴로지를 기준으로 데이터를 처리한다는 관점에서는 동일한 역할을 수행한다.

스트림즈 DSL과 프로세서 API의 차이


Streams DSL

  • 미리 제공되는 함수들을 이용하여 토폴로지를 정의하는 방식
  • 대부분의 변환 로직을 어렵지 않게 개발할 수 있도록 스트림 프로세싱에 쓰일만한 다양한 기능들을 자체 API로 제공
  • 이벤트 기반 데이터 처리를 할 때 필요한 다양한 기능들(map, join, window 등)을 대부분 제공
  • Stream DSL은 Processor API보다 비교적 추상적이며 사용하기 쉬움
  • Stream DSL만의 독특한 스트림 처리 개념 3가지가 있음
  • 요약 : 카프카를 스트림 데이터 처리 뿐만 아니라 대규모 key-value 저장소로도 사용할 수 있는 기능 제공
  • 레코드 흐름의 추상화 개념 3가지 (KStream, KTable, GlobalKTable)

Processor API

  • Streams DSL에 없는 기능이 있다면 프로세서 API 사용
  • Processor API는 Streams DSL보다 복잡한 코드를 가지지만, 데이터 처리를 토폴로지를 기반으로 수행한다는 면에서 같은 역할
  • Processor API를 사용할 때는 정의된 함수를 사용하는 것이 아니라 직접 구현해야 하기 때문에 사용하기 어려움
  • KStream, KTable, GlobalKTable 개념이 없음
  • Stream DSL보다 더 정교한 로직을 구현할 수 있는 장점이 있음
profile
Java BackEnd Developer

0개의 댓글