Apache Kafka ‐ 카프카 스트림즈 - dnwls16071/Backend_Summary GitHub Wiki
📚 카프카 스트림즈⭐
- 카프카 스트림즈는 토픽에 적재된 데이터를 실시간으로 변환하여 다른 토픽에 적재하는 라이브러리이다.
- 스트림즈는 카프카에서 공식적으로 지원하는 라이브러리이다.
- 스트림즈 애플리케이션 또는 카프카 브로커 장애가 발생하더라도 정확히 한 번(Exactly Once) 처리할 수 있도록 장애 허용 시스템을 가지고 있어 데이터 처리 안정성이 매우 뛰어나다.
- 카프카 클러스터를 운영하면서 실시간 스트림 처리를 해야하는 필요성이 있다면 카프카 스트림즈 애플리케이션으로 개발하는 것을 1순위로 고려하는 것이 좋다.
프로듀서 & 컨슈머 조합 < 스트림즈
- 스트림 데이터 처리에 있어서 필요한 다양한 기능을 스트림즈 DSL로 제공하며 필요하다면 프로세서 API를 사용하여 기능을 확장할 수 있기 때문이다.
- 컨슈머와 프로듀서를 조합하여 스트림즈가 제공하는 기능과 유사하게 만들 수 있다. 허나 스트림즈 라이브러리를 통해 제공하는 단 한 번의 데이터 처리, 장애 허용 시스템 등의 특징들은 컨슈머와 프로듀서 조합만으로 완벽하게 구현하기 어렵다.
- 다만 스트림즈가 제공하지 못하는 기능들을 구현한다면 컨슈머와 프로듀서를 조합해 구현하면 좋다.
카프카 스트림즈 내부 구조
- 스트림즈 애플리케이션은 내부적으로 쓰레드를 1개 이상 생성할 수 있으며 쓰레드는 1개 이상의 태스크를 가진다.
- 여기서 태스크는 스트림즈 애플리케이션을 실행하면 생기는 데이터 처리 최소 단위이다.
- 컨슈머의 병렬 처리를 위해 컨슈머 그룹으로 이루어진 컨슈머 쓰레드를 여러 개 실행하는 것과 비슷하다.
- 카프카 스트림즈는 컨슈머 쓰레드를 늘리는 방법과 동일하게 병렬 처리를 위해 파티션과 스트림즈 쓰레드 개수를 늘려 처리량을 늘릴 수 있다.
카프카 스트림즈 애플리케이션 스케일 아웃
- 실제 운영환경에서 장애가 발생하더라도 안정적으로 운영할 수 있도록 2개 이상의 서버로 구성하여 스트림즈 애플리케이션을 운영한다.
- 이를 통해 일부 스트림즈 애플리케이션 또는 애플리케이션이 실행되는 서버에 장애가 발생하더라도 안전하게 스트림 처리가 가능해진다.
토폴로지(Topology)
- 토폴로지란 2개 이상의 노드들과 그 노드들을 이어주는 선으로 구성된 집합을 말한다.
프로세서와 스트림
- 카프카 스트림즈에서는 토폴로지를 이루는 노드를 하나의 프로세서(Processor)라고 부르고 노드와 노드를 잇는 선을 스트림(Stream)이라고 부른다.
- 스트림은 토픽의 데이터를 뜻한다.
소스 프로세스 / 스트림 프로세서 / 싱크 프로세서
- 소스 프로세서 : 데이터를 처리하기 위해 최초로 선언해야 하는 노드로 하나 이상의 토픽으로부터 데이터를 가져오는 역할을 수행한다.
- 스트림 프로세서 : 다른 프로세서 반환한 데이터를 처리하는 역할을 한다. 변환, 분기처리와 같은 로직이 데이터 처리의 일종이라고 볼 수 있다.
- 싱크 프로세서 : 데이터를 특정 카프카 토픽으로 저장하는 역할을 하며 스트림즈로 처리된 데이터의 종착지이다.
📚 KStream, KTable, GlobalKTable⭐
KStream
- KStream은 레코드의 흐름을 표현한 것으로 메시지 키와 메시지 값으로 구성된다.
- KStream으로 데이터를 조회하면 토픽에 존재하는 모든 레코드가 출력된다.
- KStream은 컨슈머로 토픽을 구독하는 것과 동일한 선상에서 사용하는 것이라고 볼 수 있다.
KTable
- KTable은 KStream과 다르게 메시지 키를 기준으로 묶어 사용한다.
- KStream은 토픽의 모든 레코드를 조회할 수 있지만 KTable은 유니크한 메시지 키를 기준으로 가장 최신 레코드를 사용한다.
- 그러므로 KTable로 데이터를 조회하면 메시지 키를 기준으로 가장 최신에 추가된 레코드 데이터가 출력된다.
- 새로 데이터를 적재할 때 동일한 메시지 키가 있을 경우 데이터가 업데이트 되었다고 볼 수 있다. 메시지 키의 가장 최신 레코드가 갱신되었기 때문이다.
코파티셔닝
- KStream과 KTable을 조인하려면 코파티셔닝이 되어있어야 한다.
- 코파티셔닝이란 조인을 하는 2개 데이터의 파티션 개수가 동일하고 파티셔닝 전략을 동일하게 맞추는 작업이다.
- 파티션 개수가 동일하고 파티셔닝 전략이 같은 경우에는 동일한 메시지 키를 가진 데이터가 동일한 태스크에 들어가는 것을 보장한다.
- 이를 통해 각 태스크는 KStream의 레코드와 KTable의 메시지 키가 동일할 경우 조인을 수행할 수 있게 되는 것이다.
코파티셔닝되지 않은 이슈
- 조인을 수행하려는 토픽들이 코파티셔닝되어 있음을 보장할 수 없다는 것이 문제다.
- KStream과 KTable로 사용하는 2개의 토픽이 파티션 개수가 다를 수도 있고 파티션 전략이 다를 수 있다.
- 이런 경우에는 조인을 수행할 수 없다.
- 코파티셔닝이 되지 않은 2개의 토픽을 조인하는 로직이 담긴 스트림즈 애플리케이션을 실행하면 TopologyException이 발생한다.
GlobalKTable
- 위와 같이 코파티셔닝되지 않은 KStream과 KTable을 조인해서 사용하려면 KTable을 GlobalKTable로 선언하여 사용하면 된다.
- GlobalKTable은 코파티셔닝되지 않은 KStream과 데이터 조인을 할 수 있다.
- KTable과 다르게 GlobalKTable로 정의된 데이터는 스트림즈 애플리케이션의 모든 태스트에 동일하게 공유되어 사용되기 때문이다.
📚 스트림즈 주요 옵션⭐
스트림즈 DSL 중요 옵션(필수 옵션)
bootstrap.servers: 프로듀서가 데이터를 전송할 대상 카프카 클러스터에 속한 브로커의 호스트 이름:포트를 1개 이상 작성한다. 2개 이상 브로커 정보를 입력하여 일부 브로커에 이슈가 발생하더라도 접속하는 데에 이슈가 없도록 설정 가능하다.application.id: 스트림즈 애플리케이션을 구분하기 위한 고유 아이디를 설정한다. 다른 로직을 가진 스트림즈 애플리케이션들은 서로 다른application.id를 가져야 한다.
스트림즈 DSL 중요 옵션(선택 옵션)
default.key.serde: 레코드 메시지 키를 직렬화/역직렬화하는 클래스를 지정한다. 기본값은 바이트 직렬화, 역직렬화 클래스인Serdes.ByteArray().getClass().getName()이다.default.value.serde: 레코드 메시지 값을 직렬화/역직렬화하는 클래스를 지정한다. 기본값은 바이트 직렬화, 역직렬화 클래스인Serdes.ByteArray().getClass().getName()이다.num.stream.threads: 스트림 프로세싱 실행 시 실행될 쓰레드 개수를 지정한다. 기본값은 1이다.state.dir: 상태기반 데이터 처리를 할 때 데이터를 저장할 디렉터리를 지정한다. 기본값은/tmp/kafka-streams이다.
❗필터링 스트림즈 애플리케이션이란?
- 메시지 키 또는 메시지 값을 필터링하여 특정 조건에 맞는 데이터를 골라낼 때는
filter()메서드를 사용하면 된다. filter()메서드는 스트림즈 DSL에서 사용 가능한 필터링 스트림 프로세서이다.