최대한 간단하게 설명드립니다. AWS의 스트리밍 Event Broker
Written by Minhyeok Cha
오늘은 최대한 간단하게 MSK와 Kinesis Data Stream을 설명하고 각 서비스는 뭐가 다른지 비교해보는 글을 가져왔습니다.
이를 설명하기에 앞서 메세지를 보내는 큐 혹은 브로커에 관한 내용을 앞에 설명을 드리고자 합니다.
큐? 브로커? 그게 뭔데?
먼저 큐부터 말하자면 Producer에서 메세지(혹은 이벤트)를 넣고 큐에서 저장 이후 Consumer에게 전달하는 1:1 이벤트 전달 과정입니다. 이렇게 되면 '가운데의 큐가 동선을 방해하는 거 아냐? 빼는 게 더 빠를 것 같은데?'라는 생각이 들 수도 있습니다.
그런데 큐를 빼고 단순히 이벤트만 전달하는 경우 다음과 같은 에러사항이 발생할 수도 있습니다.
먼저 이벤트가 Producer에게 전달하는 과정부터 에러가 뜬다던가 Consumer에서 제대로 전달받지 못할 경우, 메세지 전달 과정의 프로세스가 꼬여서 두 개의 서비스가 고장날 확률이 높습니다. 즉 의존성에 대한 이슈가 크다는 것이 첫 번째 에러 사항입니다.
다음은 Producer와 Consumer의 복제본을 만들어 통신을 원활하게 구축해 보려했지만, 이는 메세지 전달 프로세스를 다시 한번 각 서버에 설정해 줘야 하므로 번거로울 수 있습니다. (에러보다는 인력 낭비의 문제)
세 번째는 1~12번까지의 이벤트가 담긴 메세지 중 모종의 이슈로 딜레이가 생기거나 중간의 메세지가 넘어가지를 못해 삭제가 되거나, 뒤의 메세지가 넘어가지 못하는 경우 전체적인 에러로 발생할 수 있다는 것입니다.
이러한 상황은 AWS 서비스인 AWS MSK와 Kinesis Data Stream이 해결해 줄 수 있습니다.
AWS MSK와 Kinesis Data Stream
두 가지의 공통점이자 장점은 스트림 스토리지를 가지고 있다는 것입니다.
대부분의 메시지 큐 시스템에서는 Consumer가 메시지를 성공적으로 처리하고 'acknowledgment'(ACK)를 보내거나 타임아웃을 통한 메세지 처리 방식을 사용해 해당 메시지는 큐에서 제거됩니다.
참고, 이런 상황도 있습니다!
💡 혹은 다음과 같이 병목현상을 해결하기 위해 DLQ(Dead Letter Queue)를 배치하는 방법도 있습니다만 이게 메인이 아니니까 넘어가겠습니다.
AWS MSK나 Kinesis Data Stream은 아래 그림과 같은 스트림 스토리지를 사용하고 있습니다.
단일 큐의 경우 전달의 에러가 있을 때 어느 정도 딜레이가 소요되어 Consumer에게 메세지가 바로 도달하지 못하지만, 스트림 스토리지의 샤드/파티션 내부에서는 “offset” 혹은 데이터 레코드의 “보존기간”에 의해 유지되고 있습니다.
💡 큐는 MKS와 Kinesis Data Stream에서는 파티션/샤드로 명명합니다.
다음으로는 그림 3.과 같이 1:1 즉 커플링이 아닌 그림 4.처럼 Consumer Group 속의 각 Consumer가 다수의 샤드나 파티션 중 하나씩 컨택하여 메세지를 순서대로 정리하는 디커플링의 방식을 사용하기 때문에 병목현상과 메세지 전달 보장이 가능하게 됩니다.
뿐만 아니라 Producer와 Consumer에서 추가요청 사항이 들어와도 스트림 스토리지에서 바로 엔드포인트 연결, 매핑 관리만 해주시면 괜찮습니다.
그러면 이 둘의 차이점은 무엇인가?
💡 두 서비스의 차이점은 명칭만 다르고 같은 역할을 하는 파티션 키라던가 value, offset 등이 있기 때문에 간단하게만 정리하고, 정리한 내용 외의 차이점 혹 부족한 설명은 각 서비스 소개 및 시연 블로그에 따로 정리하겠습니다.
AWS MSK
MSK는 파티션이라는 이름을 사용하고 있으며 파티셔닝의 특성은 다음과 같습니다.
오픈 소스인 Kafka에서 토픽은 하나 이상의 파티션으로 구성됩니다. ※ Kafka에서는 사용된 파티션 개수 = 브로커 개수 를 최적의 패턴이라고 합니다. 때문에 각 브로커에 파티션의 복제본을 배치해두는 구도로 작성하였습니다.
각 파티션은 독립적인 로그 파일로, 메세지는 특정 파티션에 추가됩니다.
프로듀서는 키를 기반으로 파티션에 메시지를 할당하고, 각 파티션은 다른 파티션과 독립적으로 메세지를 저장하고 전달합니다.
키가 없는 경우가 이런 라운드 로빈 방식으로 파티션에 메세지를 한 번씩 배치합니다.
AWS MSK 메시지 보존이 10MB까지 제한됩니다.
파티션은 한번 늘어나면 줄이지 못한다는 점이 있습니다. 정확히는 파티션 줄이기 자체는 가능하지만 파티션 내부의 세그먼트를 재배치 하는 것에 어려움이 있습니다.
AWS Kinesis Data Streams
Kinesis Data Streams은 샤드라는 이름을 사용하고 있으며 특성은 다음과 같습니다.
Kinesis 스트림은 샤드로 구성됩니다. 각 샤드는 특정 데이터 처리량을 갖고 있으며, 데이터 레코드는 파티션 키에 따라 샤드에 할당됩니다. 각 샤드는 독립적으로 데이터를 처리합니다.
각 샤드는 초당 최대 1MB의 데이터 입력 및 초당 2MB의 데이터 출력을 지원합니다.
Kinesis Data Streams에서는 Shard의 개수 조율이 가능합니다.
추가된 샤드에 들어오는 레코드는 새로운 샤드 중 하나에 할당되고 이는 파티션 키의 해시 값을 기준으로 결정됩니다.
각 서비스의 간단 결론
Kinesis는 관리가 쉬운 서비스를 제공하며, 간단한 스케일링과 통합을 원하는 사용자에게 적합합니다.
MSK는 더 높은 사용자 정의와 설정이 가능하며, 대규모로 확장할 수 있는 능력을 제공합니다. 추가로 오픈소스 기반이라 기존 kafka 사용자가 편합니다.
번외편 단일 매칭의 SQS
위의 두 서비스 모두 너무 어렵고 복잡하다, 그냥 테스트 혹은 연습 겸 저렴하게 AWS 서비스로 테스트를 해보고 싶은데 이런 서비스는 어디 없을까?
물론 있습니다.
AWS SQS(Simple Queue Service)는 위의 서비스와 마찬가지로 Publisher와 Consumer 입장에서 사용하게 됩니다.
각각 매칭되어 메세지를 보내주는 단순한 서비스긴 하지만 이 서비스의 큐도 사실 쓰기 나름의 역할과 어려움이 있는 건 마찬가지…
큐의 개념을 직접 테스트하여 체감하고 싶으시다면 구성도 간편한 SQS 한입 어떠신가요?
마무리
이번 내용은 제가 사용하지 않는 서비스를 공부하면서 설명을 해드리는 거라 독자분들이 어떻게 하면 더 쉽게 이해할 수 있을지 고민하면서 작성했습니다. 그러다 보니 작성 시간이 좀 길어졌네요.
두 서비스는 서로 비슷한 역할을 하고 있어서 블로그를 작성해 봤는데 사실 차이점 찾는게(AWS 측면에서) 생각보다 힘들었습니다.
심지어 Amazon Kinesis는 서버리스 기능이 있어 관리가 편하다는 장점이 있었지만 AWS MSK도 클러스터 서버리스가 생겨버리고 둘다 AWS라 파이프라인 연결 대상이 AWS 서비스라 동일한 조건이기 때문에 결국 사용량 차이 뿐이네요.
위에서 한번 언급은 했지만 더욱 상세한 글 작성을 위해 각 서비스 별 주제로 다시 돌아오겠습니다.