파편화된 데이터 수집 및 분배 아키텍처가 필요함.
예를 들어서 데이터를 생성/수집하는 아키텍처는 다음과 같을 것
생성 어플리케이션 - 소비 어플리케이션
하지만 이건 단방향임.
여기서 만약에 파이프라인이 늘어나거나 하면 굉장히 복잡해진다.
운영이 아주 어려워짐.
그래서 통합적으로 생성/수집하는 파이프라인 전체를 편리하게 관리할 수 있는 카프카가 등장함.
카프카를 사용하지 않는 경우
하나의 Target application에서 장애가 발생하면
엮여있는 Source application들도 장애가 발생한다.
연달아서 전체 파이프라인이 다 무너질수도 있다.
카프카는 생성, 소비 어플리케이션들의 각 어플리케이션의 결합도를 납춘다.
소스 어플리케이션은 데이터를 생성후 큐에 넣는다.
여기서 어느 타깃 어플리케이션으로 갈지는 고민하지 않는다.
그리고 그 데이터를 소비하기를 원하는 타깃 어플리케이션이 파티션에서 dequeue해서 소비하는 구조이다.
구분되는 데이터는 구분되는 토픽에 담긴다.
토픽은 한개이상의 파티션을 가진다.
즉 토픽은 데이터의 형태를 구분/ 파티션은 그 데이터를 집어넣는 큐
데이터를 보내는것은 프로듀서.
파티션으로 데이터를 보낸다.
프로듀서가 하나의 데이터를 생성하면 그 데이터는 여러개의 파티션중에 하나로 들어가게 된다.
컨슈머는 오래된것 부터 하나씩 파티션에서 메시지를 빼고 처리한다.
전형적인 큐 FIFO 구조이다.
하지만 큐에서는 데이터를 빼가지만,
큐에서 데이터가 삭제되는 개념은 아니다.
컨슈머가 처리한 메시지가 파티션에서 삭제되는 것은 아니기에 또 다시 처리할 수 있다.
컨슈머가 파티션에서 어디까지 컨슈밍했는지 기록을 한다.
그 기록을 커밋이라고 한다.
컨슈머가 2번까지 읽었다면 커밋을 2번으로 하게 되고, 다음에는 커밋로그를 보고 3번을 읽기 시작한다.
카프카는 데이터파이프라인으로 사용된다.
1. 높은 처리량
- 프로듀서가 데이터를 보낼때, 컨슈머가 브로커로부터 데이터를 받을때 모두 묶어서 전송한다.
- 많은 양의 데이터를 개별적으로 보내거나 소비하면 네트워크 리소스가 많이 드니까.
- 그래서 배치로 묶어서 보낸다. 그런 옵션이 준비되어 있음.
- 파티션 단위를 통해서 동일한 목적=같은 토픽의 데이터들을 여러 파티션에 분배하고 병렬적으로 처리가 가능하다.
- 파티션 개수만큰 컨슈머 갯수를 늘려서 동일 시간당 데이터 처리량을 늘린다.
- 파티션 하나당 컨슈머 하나다. 만약에 처리량을 늘려야 한다고 하면 파티션수와 컨슈머 수를 늘리면 된다. 성능 확장에 용이한 구조이다.
2. 확장성
- 데이터를 수집하고/처리하는 과정에서 우리의 예상을 넘어서는 데이터가 들어올 수 있다. 즉 예측이 힘들다. 카프카는 이러한 환경에서 안정적으로 확장이 가능하다.
- 데이터가 적을때는 브로커의 수를 적게, 많아지면 브로커의 수를 늘려서 처리가능.
- 카프카는 클러스터 환경인데, 여러개의 브로커가 하나의 클러스터에 묶여있다. 브로커는 카프카 프로세서라고 보면 된다.
- 데이터 처리량이 많아지면 브로커의 갯수를 추가적으로 늘리면 된다.
3. 영속성
- 영속성은 데이터를 생성한 프로그램이 종료되더라도 사라지지 않는 데이터의 특성을 말하는데, 카프카는 다은 메시징 플랫폼과 다르게 데이터를 메모리에 저장하지 않고 파일 시스템에 저장한다. io가 느리겠지만 캐시와 메모리를 잘 활용해서 개선했다. 브로커가 죽어도 파일시스템에 데이터가 남아있으니까 영속성이 유지된다.
- 장애가 발생해도 프로세스 재시작하면 안전하게 다시 처리가 가능하다.
4. 고가용성
- 일반적으로 클러스터에는 브로커3대로 운영한다. 프로듀서가 메시지를 만들면 그 데이터는 하나의 브로커가 아니라 클러스터 내의 다른 브로커에도 저장이 된다. 복제되서 저장되니까, 하나의 브로커가 장애가 있어도 다른 브로커들에 데이터가 남아있으니까 지속적으로 처리가 가능하다.
- 온프레미스 환경의 서버랙, 퍼블릭 클라우드의 리전단위 장애에도 데이터를 안전하게 복제할 수 있는 브로커 옵션들이 있다.
을 위해서
분산 시스템은 네트워크로 구성된 여러가지 컴퓨터 노드들의 그룹이다.
시스템 전체가 공통의 목표를 공유한다.
이런 분산 시스템의 이점은 다음과 같다.
1. 단일 시스템보다 높은 성능을 보장한다.
2. 분산 시스템 중 하나의 서버 또는 노드 등이 장애가 발생하면 다른 서버 또는 노드가 처리한다.
3. 시스템 확장이 용이하다.
간단하게 분산 시스템은 우리가 서버를 여러대를 사용해서 서비스를 유지하는것이라고 보면된다.
우리는 트래픽을 고려했을때, 단일 서버로 서비스를 유지하지 않는다.
쿠버네티스 환경에서 복수개의 파드로 전체 서비스를 구성하고, 이스티오와 같은 프록시를 통해서 트래픽을 분산한다.
카프카도 분산시스템이라서 처리량에 따라서 클러스터의 전체 노드 수를 증가시켜 처리하면 된다.
OS는 물리적 메모리의 남은 일부분을 페이지 캐시로 유지한다.
이 캐시 영역을 이용해서 전체 성능을 향상시킨다. -> 더 빠른 IO 성능
카프카도 이런 페이지 캐시를 사용해서 IO 성능을 높인다.
(카프카는 메시지를 컨슘해도 메시지가 토픽에서 삭제되지는 않는다. 파일 시스템을 이용하기 때문에 IO가 성능에 큰 영향을 미친다.)
메시지 하나 단위로 데이터를 보내고, 읽는다면 너무 잦은 서버간 IO가 발생한다.
이걸 위해서 배치단위로 produce/consume한다.
여러개로 묶어서 처리하기 때문에 네트워크 오버헤드를 줄인다의 개념이다.
토픽과 파티션의 개념
토픽은 메시지를 받을 수 있도록 논리적으로 묶은 개념.
파티션은 토픽을 구성하는 데이터 저장소 -> 수평 확장이 가능하다.
카프카 클러스터는 토픽이라는 곳에 데이터를 저장한다.
토픽은 목적성따라서 분리되면 된다.
예를 들어서, 결제 처리 후에 결제 메시지를 보내는 로직이 있다고 할때,
메시지로 보내져야 하는 데이터들을 하나의 메시지로 묶어서 구성한다.
그리고 결제 메시지는 message.after.purchase 와 같은 토픽에 전송한다.
또 결제 환불 후에도 환불 알림 메시지를 보낸다고 할때는 다른 목적의 토픽이니 message.after.refund와 같은 토픽에 메시지를 전송하면 된다.
파티션은 토픽을 분할한것이다.
토픽이 논리적 개념이라면, 파티션은 물리적인 개념이라고 보면 된다.
하나의 토픽에 여러개의 파티션을 할당한다.
결제 메시지를 message.after.purchase에 보낸다고 해보자.
그럼 해당 토픽에 들어갈 메시지는 하나의 저장소에 담기는 아니라
각 파티션에 들어가게 된다.
왜 토픽을 분할한것일까 ?
서버가 전송하고 읽는 대상이 파티션이다.
하나의 파티션만을 사용한다면, 당연히 성능적으로 좋지 않다.
여러개의 파티션을 운용한다면 병렬처리가 가능해진다.
그렇다면 무조건 파티션 수가 많은것이 좋을까 ?
그렇지 않다.
카프카에서는 각 파티션마다 메시지가 저장되는 위치를 오프셋이라고 표현한다.
하나의 토픽이 3개의 파티션으로 분할되어 있다고 한다면,
각 파티션마다 쌓이는 데이터들은 파티션마다 고유한 오프셋을 가진다.
1.0,1,2,3,4
2.0,1,2
3.0,1,2,3
3개의 파티션에 각각 데이터가 적재되고, 각 데이터는 자신이 속한 파티션에서는 고유한 오프셋값을 갖는다.
이 값을 사용해서 순차적으로 데이터 처리가 가능해진다.
producer, consumer, streams, connect는 전부 자바 기반의 라이브러리로 제공됨
1. producer는 메시지 생성
2. consumer는 메시지 소비
3. streams는 토픽에서 토픽으로의 연산. streams가 데이터를 처리해서 다시 토픽으로 보낸다.
4. connect는 다른 소스에서 데이터를 모을 수 있게끔 한다.
1. connect의 정체 ? 어차피 다 application아닌가 ? applicaction에서 connect를 통해서 데이터를 모으고 그걸 프로듀싱하는거 아닌가 ? -> 조금의 차이가 있는 부분은 커넥트는 클러스터로 구성된다는 점이다. 물론 프로듀싱하고 컨슈밍하는건 동일하지만, 클러스터로 만들어지고, 원하는 파이프라인을 템플릿으로 관리. 증가,감소가 용이하다.