11. 스트림 프로세싱
카프카의 스트림 프로세싱에 대하여 학습해봅시다.
#
서론카프카는 이벤트 스트림을 전달할 수 있는 강력한 메시지 버스로 알려져있습니다.
스트림 프로세싱 시스템의 완벽한 데이터 소스가 될 수 있습니다. ( 카프카 스트림즈에서는 메시지나 데이터를 이벤트라 부릅니다. )
이번 챕터에서는 스트림 프로세싱의 기본 개념과 모든 프로세싱 시스템에 사용되는 디자인 패턴에 대하여 살펴볼 예정입니다.
#
스트림 프로세싱이란?스트림 프로세싱의 진정한 의미에 대해서는 여전히 논란이 있습니다.
이는 마치 RDBMS 세계에서 그랬던 것 처럼, DB 엔진들의 구현과 제약이 조금씩 달라서 관계형 모델의 추상적인 정의에 혼선을 초래하는 것과 같이 스트림 프로세싱 역시 저마다 정의가 다릅니다.
스트림 프로세싱의 세계는 여전히 진화중이며 모든 스트림 프로세싱 시스템이 저마다의 구현과 제약이 존재합니다.
이벤트 스트림은 무한 데이터세트를 나타내는 추상 개념이라 할 수 있습니다.
즉 끊임없이 새로운 데이터가 전달된다는 뜻이지요. ( 계속해서 데이터가 흘러가는 것을 상상해보세요. )
이러한 이벤트 스트림에는 다음과 같은 속성이 존재합니다.
#
이벤트 스트림에는 순서가 존재한다본질적으로 이벤트란 다른 이벤트의 전, 후에 발생합니다.
예금 이벤트를 예를들어, 계좌에 돈을 먼저 입금하고 이후에 찾는 것과, 먼저 돈을 빌리고 추후에 부채 상환을 위해 나중에 입금하는 것은 엄연히 순서에 따라 의미가 다릅니다.
후자는 초과 인출이 발생하지만 전자는 그렇지 않습니다.
관계형 데이터베이스의 경우 항상 순서가 없는 것으로 간주하지만, 이벤트 스트림은 명확한 순서가 존재합니다.
#
불변 데이터 레코드이벤트 자체는 일단 발생하면 변경될 수 없습니다.
배달을 시켰는데 취소를 할 경우, 배달에 대한 이벤트는 발행되며 이후 취소에 대한 이벤트가 발행되는 식입니다.
이것이 이벤트 스트림과 데이터베이스 테이블의 또 다른 점이기도 합니다.
DB에서는 레코드를 삭제하거나 변경할 수 있지만, 그것은 모두 DB 내부에서 처리되는 트랜잭션이며 테이블 자체에 수록되지는 않습니다.
반면에 이벤트 스트림에서는 스트림 자체에 모든 트랜잭션이 수록됩니다.
레코드를 테이블에 추가 후 삭제하면 테이블에는 더 이상 레코드가 없지만 대신 redo 로그에서 두 개의 트랜잭션(추가, 삭제)를 포함합니다.
#
이벤트 스트림은 재생 가능할 수 있다이벤트 스트림은 재생이 가능합니다. (소켓을 통해 전송되는 TCP 패킷 스트림은 재생이 불가능)
대부분의 비즈니스 애플리케이션의 경우 수개월 전에 발생했던 이벤트 스트림을 재생할 수 있는 것이 중요합니다.
이는 에러를 수정하거나 스트림의 새로운 분석 방법을 시도하거나, 감사를 수행하기 위함입니다.
카프카가 성공적으로 스트림 프로세싱을 했다고 믿는 이유가 바로 여기에 있습니다.
카프카는 이벤트 스트림을 캡처하고 재생할 수 있기 떄문입니다.
만약 이런 능력이 없다면 스트림 프로세싱은 한낱 실험실의 장난감에 불과하겠지요.
#
다른 프로그래밍 패러다임과의 차이스트림 프로세싱은 하나 이상의 이벤트 스트림을 처리하는 것을 의미합니다.
스트림 프로세싱은 요청-응답, 배치 프로세스처럼 프로그래밍 패러다임의 일종입니다.
스트림 프로세싱의 이해도를 높이기 위해 다른 프로그래밍 패러다임과 비교해보겠습니다.
#
요청 응답1밀리초 이하에 수 밀리초까지의 짧은 응답 시간을 가집니다.
애플리케이션이 요청을 전송한 후 프로세싱 시스템의 응답을 기다려야합니다.
DB에서는 이 패러다임이 OLTP(Online Transaction Processing)으로 알려져 있습니다.
#
배치 프로세싱지연이 많지만, 처리량이 방대합니다.
이 프로세싱 시스템은 설정된 시간에 시작됩니다. 가령 매일 새벽 2시, 매 시간 등이 여기에 해당합니다.
#
스트림 프로세싱연속적이며 중단되지 않는 패러다임이며, 요청-응답과 배치 프로세싱 간의 격차를 줄여줍니다.
대부분의 프로세스는 수밀리초 이내의 즉시 응답을 요구하지 않지만, 그렇다고 다음 날까지 기다려주지도 않습니다.
또한 대부분의 비즈니스 프로세스는 연속적으로 발생합니다.
물품 배달 추적, 신용카드 거래 사용 내역의 알림, 수요와 공급에 기반을 둔 실시간 가격 조정 등과 같은 비즈니스는 지속적이지만 중단되지 않는 프로세싱에 해당합니다.
#
스트림 프로세싱의 정의결국 무한 데이터세트로부터 계속해서 데이터를 읽고, 처리하고, 출력을 내보낸다면 그 자체로 스트림 프로세싱입니다.
단 지속적으로 계속 진행되는 것이어야 한다. 예를 들어 매일 오전 2시에 시작해서 스트림으로부터 500개의 레코드를 읽고 결과를 출력한 후 종료한다면 그것은 스트림 프로세싱이라고 보기는 어렵습니다.
#
스트림 프로세싱 개념- 스트림 프로세싱만의 고유한 핵심 개념들에 대하여 공부해봅시다.
#
시간시간은 스트림 프로세싱의 가장 중요한 개념이자 가장 혼란스러운 개념입니다.
스트림 프로세싱에는 다음과 같은 시간 개념들이 존재합니다.
#
이벤트 시간이벤트가 발생하여 레코드가 생성된 시간입니다.
카프카는 자동으로 프로듀서 레코드에 생성 시간을 추가하고 있습니다.
#
로그 추가 시간이벤트가 카프카 브로커에 전송되어 저장된 시간입니다.
카프카 브로커는 자동으로 수신한 레코드에 생성 시간을 추가하고 있습니다.
스트림 프로세싱에서는 이벤트 발생 시간이 관심사이므로 로그 추가 시간은 덜 중요합니다.
#
처리 시간스트림 프로세싱 애플리케이션이 처리를 수행하기 위해 이벤트를 받은 시간입니다. (컨슈머가 메시지를 받은 시간)
이 시간 개념은 신뢰성이 매우 낮습니다. 왜냐하면 같은 애플리케이션의 두 쓰레드에서도 다를 수 있고, 언제 읽었는지는 항상 달라질 수 있으므로 신뢰하지 맙시다.
#
시간대에 대한 염두시간을 사용할 때는 타임존이 중요한데요, 왜냐하면 모든 스트림 시간에 단일 타임존을 적용해야하기 때문입니다.
그래서 보통은 레코드 자체에 시간대를 저장하는 경우도 있다고 합니다.
#
상태카프카에서 온라인 쇼핑 트랜잭션 스트림을 읽어 1만달러 이상의 트랜잭션들을 찾은 후, 판매 담당자에게 메일을 보내는 것은 컨슈머와 SMTP를 사용하면 몇 줄의 코드로 끝납니다.
그러나 다수의 이벤트가 포함되는 작업을 갖는 스트림 프로세싱은 복잡합니다.
현재의 한 시간동안 발생한 각 타입의 이벤트 수, 조인과 합계 평균을 구해야하는 이벤트들을 구할 때 필요한 정보가 바로 상태 입니다.
스트림 프로세싱 상태에는 다음과 같은 유형의 상태가 있습니다.
#
로컬 또는 내부 상태스트림 프로세싱 애플리케이션의 특정 인스턴스에서만 사용할 수 있는 상태입니다.
상태는 애플리케이션 내부에 포함되어 메모리에서 실행되는 DB를 사용해 유지관리됩니다.
#
외부 상태카산드라와 같은 NoSQL 외부 데이터 스토어같은 다른 시스템에 저장되고 유지 관리되는 상태입니다.
대부분의 스트림 프로세싱 애플리케이션에서는 외부 데이터스토어의 사용을 피하거나 데이터를 로컬 캐시에 유지관리하여 외부 시스템과의 통신을 최소화하려고 합니다. (지연 되므로)
#
스트림과 테이블의 이원성테이블에서의 레코드는 변경의 최종 결과 상태를 포함합니다.
스트림은 변경을 일으키는 각 이벤트가 포함된 문자열입니다.
테이블을 스트림으로 변경하기 위해서는 테이블을 수정하는 모든 이벤트를 받아서 스트림에 저장해야합니다.
이를 위해 데이터 캡처(Change Data Capture, CDC) 솔루션을 제공합니다.
스트림 프로세싱에 사용할 수 있도록 그런 변경 사항들을 카프카로 전달할 수 있는 카프카 커넥터들이 많습니다.
반대로 스트림을 테이블로 변환하기 위해서는 스트림이 포함하는 모든 변경사항을 테이블에 적용해야하며, 이를 스트림의 구체화(materializing)이라 합니다.
메모리, 내부 상태 저장소, 외부 DB 중 하나에 테이블을 생성하고, 스트림의 처음부터 끝까지 모든 이벤트를 읽어서 상태를 변경합니다.
#
타임 윈도우대부분의 스트림 작업은 타임 윈도우로 수행됩니다.
이 타임 윈도우를 적용할 때 고려해야할 점들이 있습니다.
#
타임 윈도우의 크기모든 이벤트의 평균을 매 5분 또는 15분 도는 하루 중의 어떤 타임 윈도우로 산출할 것인지를 결정해야합니다.
타임 윈도우가 커지면 지연도 커집니다.
#
타임 윈도우의 이동 빈도- 5분의 타임 윈도우로 산출된 이동 평균을 매분, 매초 또는 새로운 이벤트의 발생 중 언제 변경할 것인가를 고려합니다.
- 타임 윈도우가 스트림을 따라 진행하는 진행 간격 시간이 타임 윈도우 시간과 같다면 텀블링 윈도우라고 하며, 다른 경우를 호핑 윈도우라고 합니다.
#
타임 윈도우의 이벤트 변경 가능 시간예를 들어, 00:00 ~ 00:05 (오전 0시부터 오전 0시 5분까지) 진행한다면, 한 시간이 지난 후, 00:02(오전 0시 2분)의 이벤트 시간에 추가될 결과값을 얻게되었다면 어떻게 해야할까요?
이상적으로는 이벤트가 추가되는 특정 시간대의 타임 윈도우를 정의할 수 있다. 가령, 이벤트를 4시간 늦게까지 받는다면 그것으로 산출되는 결과값을 다시 계산하여 변경하고, 4시간 이후의 이벤트는 무시해버린다던지 할 수 있습니다.
#
스트림 프로세싱 디자인 패턴모든 스트림 프로세싱 시스템은 서로 다릅니다.
컨슈머와 프로세싱 로직 및 프로듀서를 조합한 것이 있는가 하면, 머신 러닝 기반의 스파크 스트리밍처럼 클러스터가 수반되는 것들도 있습니다.
스트림 프로세싱 시스템에는 기본적인 디자인 패턴들이 있으며 이것들은 스트림 프로세싱 아키텍처의 공통적인 요구사항에 대한 솔루션으로 알려져 있습니다.
잘 알려진 몇 가지 패턴을 보고 어떻게 사용되는지 살펴봅시다.
#
단일 이벤트 프로세싱가장 기본적인 스트림 프로세싱 입니다.
각 이벤트를 별개로 처리하는 것입니다.
이 패턴의 스트림 프로세싱 애플리케이션은 스트림으로부터 이벤트를 읽고 변경한 후 다른 스트림으로 씁니다.
#
로컬 상태를 사용한 스트림 프로세싱카프카 스트림의 상태 정보를 로컬에 저장해놓고 사용할 수 있습니다.
가령 당일의 주식 최저가와 최고가를 산출하기 위해 스트림의 모든 가격들을 차례대로 비교해야 하는 경우 로컬 상태를 사용할 수 있습니다.
같은 주식 종목의 모든 이벤트를 카프카의 같은 파티션에 쓰도록 하고, 애플리케이션의 각 인스턴스에서 자신에게 할당된 파티션들의 모든 이벤트를 가져오면 됩니다.
애플리케이션의 각 인스턴스가 자신에게 할당된 파티션에 지정된 주식 종목의 상태를 유지관리할 수 있다는 의미입니다.
#
다단계 프로세싱가령 매일 상위 10개의 주식을 알아야 한다면 어떤 패턴을 적용해볼 수 있을까요?
로컬 상태를 갖는 각 인스턴스에서 각 종목별 주가 상승/하락을 산출한 후 새로운 토픽으로 하나의 파티션에 씁니다.
그리고 이 파티션을 하나의 애플리케이션 인스턴스가 읽어서 당일의 상위 10개 주식을 알 수 있는 것이지요.
#
카프카 스트림즈- 카프카 스트림즈 라이브러리가 실제로 동작하는 방법을 더 잘 이해하기 위해 API 내부 메커니즘을 알아봅시다.
#
토폴로지 생성하기모든 스트림 애플리케이션은 최소 하나의 토폴로지를 구현하고 실행합니다.
토폴로지는 모든 이벤트가 입력에서 출력으로 이행하는 동안 수행되는 작업과 변환 처리의 집합을 나타냅니다.
간단한 애플리케이션도 나름의 토폴로지가 존재합니다.
토폴로지는 프로세서들로 구성되며, 그것들은 토폴로지 그래프의 노드에 해당합니다.
대부분의 노드에서는 필터와 맵과 같은 데이터 처리 작업을 구현합니다.
토픽으로부터 데이터를 읽어 전달하는 소스 프로세서도 존재합니다.
이전의 프로세서로부터 데이터를 받아 토픽에 쓰는 싱크 프로세서도 존재합니다.
토폴로지는 하나 이상의 소스 프로세서로 시작해 싱크 프로세서로 끝납니다
#
토폴로지 규모 확장하기카프카 스트림즈는 하나의 애플리케이션 인스턴스 내부에 다수의 실행 스레드를 허용하고, 분산된 애플리케이션 인스턴스 간의 load balancing을 지원함으로써 규모를 확장합니다.
카프카 스트림즈 엔진은 토폴로지의 실행을 태스크로 분할하여 병행 처리합니다.
태스크의 개수는 애플리케이션이 처리하는 토픽의 파티션 개수에 따라 카프카 스트림즈가 결정합니다.
각 태스크는 전체 파티션 중 일부를 처리하는 책임을 갖습니다.
애플리케이션이 생성하는 태스크들의 일부로 모든 스레드가 실행될 수 있습니다.
만약 애플리케이션의 여러 인스턴스가 다수의 서버에서 실행중이라면, 서로 다른 태스크들이 각 서버의 스레드로 실행됩니다.
스트리밍 애플리케이션이 구모를 확장할 수 있는 방법이 바로 이것입니다.
- 스트림 프로세싱 태스크는 다수의 스레드와 서버에서 실행될 수 있습니다.
#
리파티션애플리케이션에 따라 리파티션이 필요한 경우에 태스크간 의존 관계가 생길 수 있습니다.
모든 이벤트는 유저 ID를 키로 갖는다고 가정해보겠습니다.
그런데 유저가 아닌 페이지별로 통계를 구성해야한다면? 이메일 별로 생성해야한다면?
예를 들어, 태스크 1이 파티션 1의 이벤트를 처리하고 그것을 리파티션하는 프로세서에 전송하여 쓰게 한 후 그것을 다른 태스크가 읽어서 처리하게 할 수 있습니다.
카프카 스트림즈는 새로운 키와 파티션을 갖는 새로운 토픽에 이벤트를 쓰고, 다른 태스크들이 새로운 토픽의 이벤트를 읽고 계속해서 처리해나갑니다.
리파티션을 할 때는 두 번 째 서브토폴로지는 첫 번째 서브토폴로지의 결과를 처리하므로 첫 번째 서브토폴로지에 의존성을 갖습니다.
그러나 첫 번째 태스크 와 두 번째 태스크는 독립적이며 병행으로 실행될 수 있습니다.
왜냐면 첫 번째 태스크는 토픽에 이벤트를 쓰고, 두 번째 태스크는 토픽의 이벤트를 읽어서 처리하기 때문이죠.
두 태스크는 상호 통신하지 않으며, 공유 자원도 상요하지 않으므로 같은 스레드나 서버에서 실행될 필요가 없습니다.
#
장애에서 살아남기애플리케이션의 규모를 확장하게 해주는 앞의 토폴로지에서도 장애를 처리할 수 있습니다.
애플리케이션에 장애가 생겨 다시 시작해야할 때 카프카 스트림즈의 마지막 위치를 찾을 수 있고, 장애가 생기기 전 커밋했던 마지막 오프셋부터 처리가 가능합니다.
로컬 상태를 저장한 데이터 스토어가 유실된 경우라면 카프카에 저장된 변경 로그를 사용해 스트림 애플리케이션이 항상 다시 생성할 수 있습니다.
카프카 스트림즈는 태스크의 높은 가용성을 제공하기 위해 카프카의 컨슈머 조정도 해줍니다.
하나의 태스크에 장애가 생기면, 스트림 애플리케이션의 실행 가능한 스레드나 다른 인스턴스가 있다면 사용 가능한 스레드에서 해당 태스크가 다시 실행됩니다.
이것은 커슈머 그룹이 컨슈머 중 하나의 장애를 처리하는 것과 유사합니다.
#
스트림 프로세싱 이용 사례이 장 앞에서도 이야기 헀듯이, 이벤트가 빨리 처리되길 원하지만 그렇다고 수밀리초까진 아닐 때 스트림 프로세싱은 유용합니다.
지금부터는 실제 시나리오를 몇 가지 알아보겠습니다.
#
고객 서비스대형 호텔과 같이 객실을 예약하고 확인 이메일과 영수증을 전송해야하는 경우에 사용해볼 수 있습니다.
실시간 서비스에 스트림즈를 사용해볼 수 있습니다.
#
사물 인터넷- 집안의 온도를 조정하고 세탁기의 세제 보충을 지시하는 등의 IOT 기기들에 명령 이벤트를 처리하는데 사용할 수 있습니다.
#
부정 적발이상 탐지(anomaly detection)이라고 부르는 시스템에 해를 끼치는 사람을 알아낼 때 역시 스트림즈를 사용해볼 수 있습니다.
신용카드 부정 사용, 주식 거래 부정 적발 등과 같은 곳에서 말이죠.
#
스트림 프로세싱 프레임워크를 사용하는 애플리케이션의 유형스트림 프로세싱 프레임워크를 선택할 때 우리가 작성하려는 애플리케이션의 유형을 고려해봐야 합니다.
애플리케이션의 유형은 다음과 같습니다.
#
ingest하나의 시스템에서 다른 시스템으로 전달하는 목적.
전달받는 시스템에 맞춰 데이터를 변경해야합니다.
#
low milliseconds actions- 즉시 응답을 요구하는 애플리케이션.
#
asynchronous microservices마이크로서비스는 더 큰 프로세스를 대신하여 작은 액션을 수행합니다.
애플리케이션의 성능을 향상시키기 위해 이벤트를 캐싱하는 방법으로 로컬 상태를 유지 관리 해볼 수 있습니다.
#
near real-time data analytics- 실시간에 가까운 데이터 분석을 위해 복잡한 집계와 조인을 사용하려는 경우.
#
카프카 프레임워크 선택 기준#
operability of the system- 업무용 배포가 쉬운지? 모니터링과 문제 해결이 쉬운지? 규모의 확장이나 축소가 용이한지? 기존 구조와 잘 통합될 수 있는지?
#
makes hard things easy대부분의 시스템에서는 진보된 타임 윈도우를 집계해줄 수 있고 로컬 캐시를 지원한다고는 합니다.
그러나 그런 일들을 정말로 쉽게 해주는지? 시스템의 규모 조정과 복구와 같이 세부적인 것들을 처리해주는지 확인해보아야합니다.
#
community- 스트림 프로세싱 애플리케이션이 오픈소스에서 얼마나 활발하게 커뮤니티가 형성되어있는지를 잘 봐야합니다.
#
요약스트림 프로세싱이 무엇인지에 대해 알아보았습니다.
스트림 프로세싱의 중요한 개념과 디자인 패턴들에 대하여 공부했습니다.
스트림즈 아키텍처의 개요를 보았고 내부적으로 어떻게 동작하는지도 살펴보았습니다.
마지막으로 스트림 프로세싱 이용사례를 보고 서로 다른 스트림 프로세싱 프레임워크를 비교 선택하는 방법도 알아보았습니다.
계정 개발팀 모두들 스터디 하느라 다들 수고 많으셨습니다!!
#
Reference카프카 핵심 가이드