이 글은 책 내용을 토대로 작성하였습니다.
목차
스트림
스트림 처리의 정의
-
n분 주기로 동작을 하거나 특정일에 동작을 하는 고정된 시간 개념을 버리고
이벤트가 발생할 때마다 처리를 한다는게 스트림 처리의 정의이다.
이벤트 스트림 전송
로그 기반 메시지 브로커
-
로그 기반 메시지 브로커이란
DB의 지속성 있는 저장 방법과
메시징 시스템의 지연 시간이 짧은 알림 기능을 합친 개념이다.
-
생산자가 보낸 메시지는 로그 끝에 추가하고
소비자는 로그를 차례로 읽어 메시지를 받는다.
-
소비자가 로그 끝에 도달하면 새 메시지가 추가됐다는 알림을 기다린다.
ex) tail -f 명령어는 파일에 추가되는 데이터를 감시하는데 위 구조와 같다.
로그 파티셔닝
-
처리량을 높이기 위해 하나의 디스크만 사용하지 않고 로그를 파티셔닝하기도 한다.
-
다른 파티션은 다른 장비에서 서비스할 수 있다.
그러면 각 파티션은 독립적으로 R/W 가능한 분리된 로그가 된다.
-
토픽은 같은 형식의 메시지를 전달하는 파티션들의 그룹으로 정의한다.
-
각 파티션 내에서 브로커는 모든 메시지에 오프셋을 부여하는데
해당 파티션 내에서만 순서 보장이 되므로
다른 파티션 간 메시지의 순서는 보장되지 않는다.
-
이런 방식으로 동작하는 로그 기반 메시지 브로커로는
아파치 카프카, 아마존 키네시스 스트림, 트위터의 분산 로그가 있다.
-
이런 메시지 브로커는 모든 메시지를 디스크에 저장하지만
여러 장비에 메시지를 파티셔닝해 초당 수백만 개의 메시지를 처리할 수 있고
메시지를 복제함으로써 장애에 대비할 수 있다.
로그 방식 vs 전통적인 메시징 방식
-
로그 기반 접근법은 당연히 팬 아웃 메시징 방식을 제공한다.
소비자가 독립적으로 로그를 읽을 수 있고
메시지를 읽어도 로그에서 삭제되지 않기 때문이다.
-
개별 메시지를 소비자 클라이언트에게 할당하지 않고
소비자 그룹에 속해있는 n개의 소비자 클라이언트 간 로드 밸런싱을 위해
브로커는 소비자 그룹 노드들에 전체 파티션을 할당할 수 있다.
// 소비자 그룹 = 소비자 클라이언트1 + 소비자 클라이언트2 + … + 소비자 클라이언트n
-
각 클라이언트는 할당된 파티션의 메시지를 모두 소비한다.
일반적으로 소비자에 로그 파티션이 할당되면
소비자는 단일 스레드로 파티션에서 차례로 메시지를 읽는다.
이런 방식의 로드 밸런싱 방법은 몇 가지 단점이 있다.
첫 번째 단점
-
토픽 하나를 소비하는 소비자 클라이언트(=노드)의 수는
많아야 해당 토픽의 로그 파티션 수로 제한된다.
같은 파티션 내 메시지는 같은 노드로 전달되기 때문이다.
두 번째 단점
- 특정 메시지 처리가 느리면 파티션 내 후속 메시지 처리가 지연된다.
결론
-
메시지 처리 비용 비쌈
&& 메시지 단위로 병렬화 처리 희망
&& 메시지 순서 중요 X
=> JMS/AMQP 방식의 메시지 브로커가 적합하다.
-
처리량이 많음
&& 메시지 처리 속도 빠름
&& 메시지 순서 중요
=> 로그 기반 접근법이 효과적이다.
디스크 공간 사용
-
로그를 계속 추가만 한다면 디스크 공간이 부족해지고
디스크 공간을 재사용하기 위해
로그를 여러 조각으로 나누고 오래된 조각을 삭제하거나 보관 저장소로 이동한다.
-
소비자 처리 속도가 느려 메시지가 생산되는 속도를 따라잡지 못하면
소비자가 너무 뒤처져 소비자 오프셋이 이미 삭제한 조각을 가리킬 수도 있다.
즉 메시지 일부를 잃어버릴 가능성이 있다.
-
로그는 크기가 제한된 버퍼로 구현하고
버퍼가 가득 차면 오래된 메시지 순대대로 버린다.
ex) 원형 버퍼(Circular Buffer), 링 버퍼(Ring Buffer)
-
모든 메시지를 디스크에 기록하므로
로그 처리량은 일정하고
기본적으로 메모리에 메시지를 유지하고
큐가 너무 커지면 디스크에 기록하는 메시징 시스템과는 반대다.
-
그래서 메모리에 메시지를 유지하는 시스템은
큐가 작을 때는 빠르지만 디스크에 기록하기 시작하면 매우 느려진다.
생산자 속도 > 소비자 속도
-
로그 기반 접근법은
소비자가 메시지를 전송하는 생산자를 따라갈 수 없을 때
선택할 수 있는 선택지 중 하나인 버퍼링 형태이다.
-
만약 소비자가 뒤처져 필요한 메시지가
디스크에 보유한 메시지보다 오래되면 필요한 메시지를 읽을 수 없다.
-
이런 불상사를 막기 위해
개발자는 소비자가 로그의 헤드로부터 얼마나 떨어졌는지 모니터링하면서
만약 일정 기준 뒤처진다면 적절한 조치를 할 수 있다.
-
만약 버퍼가 커진다면
개발자는 처리가 느린 소비자의 문제를 고쳐
메시지를 잃기 전에 정상화할 수 있는 시간을 충분히 벌 수 있다.
장점
-
어떤 소비자의 처리 속도가 느려 메시지를 잃기 시작해도
해당 소비자만 영향을 받고 다른 소비자는 영향을 받지 않는다.
-
이런 특징을 살려
운영 서비스에 영향을 주지 않으면서
개발, 테스트, 디버깅 목적으로
운영 로그를 소비하는 실험을 할 수 있으므로 운영상 상당한 장점이 될 수 있다.
오래된 메시지 재생
-
로그 기반 메시지 브로커는 메시지를 소비하더라도
로그를 변화시키지 않는 읽기 전용 (READ ONLY)으로 동작한다.
-
그러므로 소비자 오프셋을 조작하여
오래된 메시지를 다시 읽어 재처리한다든지
반복적으로 데이터를 읽을 수도 있다.
-
즉 로그 기반 메시징 시스템은 많은 실험을 할 수 있고
오류와 버그를 복구하기 쉬우므로 굉장히 좋은 시스템이라 할 수 있다.