Search

Kinesis Stream Pipeline을 통한 DB, S3 적재 설계

개요

현재 진행하고 있는 프로젝트는 채팅 수집기능이 핵심이며, 그보다 더 중요한 것은 없다. 따라서 채팅 수집은 장애 없이 이뤄져야한다는 점에서 설계에 대한 고찰을 꽤나 한 편이다.
최초 단일 서버로 구성할 당시엔 동일 서버 내에 수집기능을 배치로 돌리고, API 서버도 함께 사용했다. 문제는, 웹소켓 브로드캐스트를 통해 데이털르 수집한 직후 DB에 적재하는 형태의 구조였다. 수집 채널이 조금만 늘어나도 수집기와 DB의 부하가 기하급수적으로 늘어났음이 자명했다. 어느 순간 DB 접속이 힘들어졌다. 이런 문제에 직면한 뒤에 구조를 변경할 계획을 세웠다.
EKS 내에 여러 채팅 수집 인스턴스들을 배치하고, 채팅 수집기를 MSA 형태로 기존 프로젝트에서 분리하는 작업을 진행했다. 채팅 수집기가 여러 채널을 수집하다보니 중복처리에 문제가 생겼다. EKS 내에 동일한 인스턴스들이 생성되고 동일한 채널을 바라볼 때 DB에 적재된 채팅이 중복이 되는 것이었다. 이런 문제를 해결하기 위해 Redis를 중간에 배치하여 분산 Lock을 통해 채널을 관리하여 오토스케일링을 통해 주기적으로 늘어나는 인스턴스들의 수집 채널을 동적할당하기 위함이었다. 이제 각 인스턴스는 별도의 채널을 수집하고 SQS로 던지는 형태가 되었고, Consumer 서버를 통해서 DB에 적재를 하면 전반적인 채팅 수집 구조는 완성될 예정이었다.
다만 이 지점에서 AWS 멘토님께 상담을 받고나니, 애초에 채팅이라는 데이터를 DB에만 적재하는게 이후 확장성에 문제가 있을 수 있다는 답변을 받았다. 채팅 수집 이후에는 데이터를 활용한 지표와 AI를 통한 분석을 진행할 예정이었고. 이러한 분석이 진행될 때마다 DB를 바라보는 것은 부하가 분명 있을거라는 피드백이었다.
그러다보니 SQS와 같이 메시지가 소비되는 구조에서는 병렬 처리를 하게 될 때 Consumer가 DB 적재와 S3 적재를 모두 담당해야 한다는 문제가 생겼다. SNS를 통해 구독 주체를 나눠서 할 수도 있지만 효율적이지 않다는 점에서 모든 샤드를 각 Consumer 가 병렬 소비할 수 있는 Kinesis Stream을 이용하게 되었다. Kinsis Stream은 앞서 설명한 것과 같이 메시지가 소비되는 형태라기보단 각 Consumer 가 각각 커서를 활용해 어느 지점까지 데이터를 풀링해왔는지를 기억해두는 형태로 사용 할 수 있다. 여기선 별도로 서버를 만들기보다는 Lambda를 활용하여 RDB에 적재하고, Raw Data는 Kinesis Firehose를 통해 S3에 적재하는 형태로 설계를 하게 되었다.