Gidhub BE Developer

[데이터 중심 애플리케이션 설계] 11장. 스트림 처리 : 1. 이벤트 스트림 전송 - 2편

2022-06-21
goodGid

이 글은 내용을 토대로 작성하였습니다.

목차

  1. 이벤트 스트림 전송 - 1편

  2. 이벤트 스트림 전송 - 2편

  3. DB와 스트림 - 1편

  4. DB와 스트림 - 2편

  5. 스트림 처리 - 1편

  6. 스트림 처리 - 2편


스트림

스트림 처리의 정의

  • n분 주기로 동작을 하거나 특정일에 동작을 하는 고정된 시간 개념을 버리고

    이벤트가 발생할 때마다 처리를 한다는게 스트림 처리의 정의이다.


이벤트 스트림 전송

로그 기반 메시지 브로커

  • 로그 기반 메시지 브로커이란

    DB의 지속성 있는 저장 방법과

    메시징 시스템의 지연 시간이 짧은 알림 기능을 합친 개념이다.

  • 생산자가 보낸 메시지는 로그 끝에 추가하고

    소비자는 로그를 차례로 읽어 메시지를 받는다.

  • 소비자가 로그 끝에 도달하면 새 메시지가 추가됐다는 알림을 기다린다.

    ex) tail -f 명령어는 파일에 추가되는 데이터를 감시하는데 위 구조와 같다.


로그 파티셔닝

  • 처리량을 높이기 위해 하나의 디스크만 사용하지 않고 로그를 파티셔닝하기도 한다.

  • 다른 파티션은 다른 장비에서 서비스할 수 있다.

    그러면 각 파티션은 독립적으로 R/W 가능한 분리된 로그가 된다.

  • 토픽은 같은 형식의 메시지를 전달하는 파티션들의 그룹으로 정의한다.

  • 각 파티션 내에서 브로커는 모든 메시지에 오프셋을 부여하는데

    해당 파티션 내에서만 순서 보장이 되므로

    다른 파티션 간 메시지의 순서는 보장되지 않는다.

  • 이런 방식으로 동작하는 로그 기반 메시지 브로커로는

    아파치 카프카, 아마존 키네시스 스트림, 트위터의 분산 로그가 있다.

  • 이런 메시지 브로커는 모든 메시지를 디스크에 저장하지만

    여러 장비에 메시지를 파티셔닝해 초당 수백만 개의 메시지를 처리할 수 있고

    메시지를 복제함으로써 장애에 대비할 수 있다.


로그 방식 vs 전통적인 메시징 방식

  • 로그 기반 접근법은 당연히 팬 아웃 메시징 방식을 제공한다.

    소비자가 독립적으로 로그를 읽을 수 있고

    메시지를 읽어도 로그에서 삭제되지 않기 때문이다.

  • 개별 메시지를 소비자 클라이언트에게 할당하지 않고

    소비자 그룹에 속해있는 n개의 소비자 클라이언트 간 로드 밸런싱을 위해

    브로커는 소비자 그룹 노드들에 전체 파티션을 할당할 수 있다.

    // 소비자 그룹 = 소비자 클라이언트1 + 소비자 클라이언트2 + … + 소비자 클라이언트n

  • 각 클라이언트는 할당된 파티션의 메시지를 모두 소비한다.

    일반적으로 소비자에 로그 파티션이 할당되면

    소비자는 단일 스레드로 파티션에서 차례로 메시지를 읽는다.

    이런 방식의 로드 밸런싱 방법은 몇 가지 단점이 있다.

첫 번째 단점

  • 토픽 하나를 소비하는 소비자 클라이언트(=노드)의 수는

    많아야 해당 토픽의 로그 파티션 수로 제한된다.

    같은 파티션 내 메시지는 같은 노드로 전달되기 때문이다.

두 번째 단점

  • 특정 메시지 처리가 느리면 파티션 내 후속 메시지 처리가 지연된다.

결론

  • 메시지 처리 비용 비쌈

    && 메시지 단위로 병렬화 처리 희망

    && 메시지 순서 중요 X

    => JMS/AMQP 방식의 메시지 브로커가 적합하다.

  • 처리량이 많음

    && 메시지 처리 속도 빠름

    && 메시지 순서 중요

    => 로그 기반 접근법이 효과적이다.


디스크 공간 사용

  • 로그를 계속 추가만 한다면 디스크 공간이 부족해지고

    디스크 공간을 재사용하기 위해

    로그를 여러 조각으로 나누고 오래된 조각을 삭제하거나 보관 저장소로 이동한다.

  • 소비자 처리 속도가 느려 메시지가 생산되는 속도를 따라잡지 못하면

    소비자가 너무 뒤처져 소비자 오프셋이 이미 삭제한 조각을 가리킬 수도 있다.

    즉 메시지 일부를 잃어버릴 가능성이 있다.

  • 로그는 크기가 제한된 버퍼로 구현하고

    버퍼가 가득 차면 오래된 메시지 순대대로 버린다.

    ex) 원형 버퍼(Circular Buffer), 링 버퍼(Ring Buffer)

  • 모든 메시지를 디스크에 기록하므로

    로그 처리량은 일정하고

    기본적으로 메모리에 메시지를 유지하고

    큐가 너무 커지면 디스크에 기록하는 메시징 시스템과는 반대다.

  • 그래서 메모리에 메시지를 유지하는 시스템은

    큐가 작을 때는 빠르지만 디스크에 기록하기 시작하면 매우 느려진다.


생산자 속도 > 소비자 속도

  • 로그 기반 접근법은

    소비자가 메시지를 전송하는 생산자를 따라갈 수 없을 때

    선택할 수 있는 선택지 중 하나인 버퍼링 형태이다.

  • 만약 소비자가 뒤처져 필요한 메시지가

    디스크에 보유한 메시지보다 오래되면 필요한 메시지를 읽을 수 없다.

  • 이런 불상사를 막기 위해

    개발자는 소비자가 로그의 헤드로부터 얼마나 떨어졌는지 모니터링하면서

    만약 일정 기준 뒤처진다면 적절한 조치를 할 수 있다.

  • 만약 버퍼가 커진다면

    개발자는 처리가 느린 소비자의 문제를 고쳐

    메시지를 잃기 전에 정상화할 수 있는 시간을 충분히 벌 수 있다.

장점

  • 어떤 소비자의 처리 속도가 느려 메시지를 잃기 시작해도

    해당 소비자만 영향을 받고 다른 소비자는 영향을 받지 않는다.

  • 이런 특징을 살려

    운영 서비스에 영향을 주지 않으면서

    개발, 테스트, 디버깅 목적으로

    운영 로그를 소비하는 실험을 할 수 있으므로 운영상 상당한 장점이 될 수 있다.


오래된 메시지 재생

  • 로그 기반 메시지 브로커는 메시지를 소비하더라도

    로그를 변화시키지 않는 읽기 전용 (READ ONLY)으로 동작한다.

  • 그러므로 소비자 오프셋을 조작하여

    오래된 메시지를 다시 읽어 재처리한다든지

    반복적으로 데이터를 읽을 수도 있다.

  • 즉 로그 기반 메시징 시스템은 많은 실험을 할 수 있고

    오류와 버그를 복구하기 쉬우므로 굉장히 좋은 시스템이라 할 수 있다.


Refernece


Recommend

Index