티스토리 뷰

 

1편에서 부터 이어지는 내용

 

2024.03.30 - [일상] - 가상면접사례로 배우는 대규모 시스템 설계 기초 -1 을 읽고

 

12장. 채팅 시스템 설계

요청 사항이 조금 빡세다.

 

DAU 5천만에 일반적으로 알고 있는 모든 메신저의 기능 지원, 메시지 길이 10만자까지 지원해야 한다.

 

너무 많은 요구 사항이 있고, 대용량 데이터를 저장해야 하는 작업이라 DB부터 실시간성을 지원하기 위한 방법론까지 필요하다. 

 

우선, 채팅 서비스 접속에는 HTTP의 keep alive 헤더를 이용한 방식을 제안한다.

 

하지만 메시지 수신 시나리오는 조금 더 복잡한 방식을 고려해야 한다.

 

폴링 방식은 접속한 사용자가 연결이 끊어졌는지 알 수 있는 방법이 없고, 답 해줄 메시지가 없는 경우에도 응답을 대기하다가 타임아웃 후 재연결하기 때문에 비효율적이다.

 

그리고 stateless하기 때문에 이전에 접속했던 채팅 서버에 재접속이 되지 않을 수도 있음.

 

그런 점에서 웹소켓은 양방향 통신이라 위 단점들을 전부 해결할 수 있음. 다만, 연결이 된 후에는 지속적으로 유지가 잘 되어야 하기 때문에, 연결관리를 효율적으로 해야한다.

 

실시간 성을 제공해야하는 채팅 서버와 접속 상태 서버를 제외하고는 웹소켓을 사용하지 않는다. 연결 유지 비용이 비쌈 ㅠ

 

저장소는 수평적 규모확장이 쉽고, 데이터 접근 지연시간이 낮고, 롱테일 문제가 없는 NoSQL 형식의 키-값 저장소를 권장한다. 

 

사용자에게 적합한 채팅 서버를 추천하는 방식은 여러 구현 방식(클라이언트의 위치, 서버 용량)이 있을 수 있다. 

 

아파치 주키퍼를 이용해 사전에 정의한 기준에 따라 최적의 채팅 서버를 골라 줄 수 있음

 

메시지 흐름도 흥미로운 주제.

 

1:1 채팅 메시지 흐름은 비교적 간단하지만, 여러 단말 사이의 메시지 동기화, 그룹 채팅에서의 메시지 흐름은 이슈가 있을 수 있다. 

 

여러 단말은 각각의 웹소켓을 연동해 사용하고, 채팅 메시지는 동기화 큐를 이용해 해결했다.

 

접속 상태 관리는 박동 이벤트(헬스체크와 같은 방법인 듯?)로 관리하고,

 

접속 상태 갱신은 대규모로 갈 수록 실시간성을 보장하기 힘들기 때문에, 접속했을 때 혹은 수동으로 가져가게 끔 한다.

 

주키퍼를 이용한 최적의 채팅 서버를 골라준다는 개념이 잘 이해되지 않는데, 잘 설명되지 않아서 아쉬웠다. 

 

조금 더 디테일하게 봤으면 하는 부분들이 많은데, 폴링/웹소켓에 대한 설명과 단순히 HTTP 통신으로 구현된 부분을 다 짚고 갔던 부분이 아쉬웠다. 

 

13장. 검색어 자동완성 시스템

 

위 이미지와 같이 검색어 자동완성을 도와주는 시스템을 어떻게 설계할 것인가? 를 다룬다.

 

구글을 사용해보면 진짜 빠르고, 아래의 요구사항을 모두 만족하는 것 같다.

 

요구사항으로는 빠른 응답속도, 연관성, 정렬, 규모 확장성(DAU 천만명) 기준이다.

 

개략적으로 보면, 데이터 수집 서비스와 질의 서비스로 나뉜다.

 

사용량이 적을 땐 단순 쿼리로도 해결이 가능하다. 제공하려는 자동완성의 개수를 줄이면 속도도 괜찮을 것이다.

 

select 쿼리를 이용한 접근법은 최적은 아니지만 출발로는 좋은 방안이다.

 

규모확장성을 지원하려면 트라이 자료구조를 알아야한다.

 

트라이 자료 구조는 트리 형식의 자료 구조로 노드에 글자와 인기도를 담고 있어서 검색에 시간 복잡도를 크게 줄여준다.

 

검색어 자동 완성 시스템은 트라이로 구성된 데이터베이스를 구성하는 게 중요하고, 나머지는 일반적인 api서버와 구조가 다를게 없다.

 

트라이의 크기가 너무 커질 경우 서버를 나눠야하는데, 어떤식으로 나눠야하나 논의가 필요하다.

(단순히 생각하면 알파벳 별로도 나눌 수 있으나, x로 시작하는 단어는 많지 않아 좋은 방법은 아니다.)

 

이 외에도 필터링, 다국어 지원 등의 문제가 있을 수 있다. 다국어 지원은 유니코드를 생각해보면 된다고한다.

 

사실 이번 장은 트라이를 어떻게 구성할 것인가? 가 가장 큰 이슈였다. 서버의 구조 자체는 매우 단순했다.

 

데이터의 규모가 너무 커서 어떤 DB로 저장해야하고, 트라이를 어떻게 갱신하고 삭제할 것인가도 이슈가 된다.

 

자세히 언급되진 않았지만 다국어 지원을 해야하므로 서버도 지역별로 있어야되고, 캐시의 역할이 클 것 같다. 


14장. 유튜브 설계

유튜브는 상상을 초월하는 사용량을 보여준다. 2020년 기준인데, 현재는 더 늘었을거다.

 

1. MAU : 20억

2. 매일 재생되는 비디오 수 : 50억

3. 5천만명의 창작자

4. 모바일 인터넷 전체 트래픽 가운데 27% 유튜브가 점유

 

상상을 초월하는 사용량이다.

 

비디오 스트리밍 서비스 설계 - 빠른 업로드, 원활한 재생, 품질 선택, 낮은 비용, 가용성 확장성 안정성, 다중 클라 지원

 

원활한 재생을 위해선 CDN 사용이 필수적인데, CDN은 비디오를 사용할 경우 엄청난 요금이 과금된다.

- 비용을 줄이는 설계를 필요로 함

 

비디오 업로드 절차

메타데이터를 저장하는건 일반적인 API 서버에서 처리가 가능하나 비디오는 비동기적인 트랜스코딩을 적용하고 CDN에 보낸다. 여기서 원본은 BLOB 저장소(이진 데이터를 하나의 개체로 보관하는 DB)에 저장한다.

트랜스코딩은 비디오 인코딩이라 부르기도 하는 절차, 비디오의 포맷을 변환하는 절차. 단말이나 대역폭 요구사항에 마즌 최적의 비디오 스트림 제공을 위함

 

트랜스코딩 완료 큐를 사용하는데, 이벤트를 pub/sub 하는 방식으로 사용하지 싶다.

 

비디오를 pending 상태로 만들어 두고, 완료되면 cdn 주소와 상태를 갱신하는 방식으로 구성.

 

비디오 스트리밍 절차

스트리밍은 원격지의 비디오로부터 지속적으로 비디오 스트링믈 전송받아 영상을 재생하는 것을 의미

스트리밍 프로토콜을 알아둬야 함. ex MPEG-DASH

비디오는 CDN에서 바로 스트리밍된다. 사용자가 있는 엣지 서버에서 전송되니 전송 지연은 거의 없다.

 

상세 설계

 비디오 트랜스코딩과 스트리밍 부분은 최적화가 필요하다.

 

비디오 트랜스코딩 고려 사항

1. 원본의 큰 저장 공간

2. 특정 비디오 포맷만 지원하는 클라이언트

3. 대역폭에 따른 화질 설정 후 전송

4. 수시로 바뀌는 네트워크 상황 고려

5. 처리 과정의 병렬성을 높이기 위해서 DAG(유향 비순환 그래프) 모델 도입 고려

 

전처리기 -> DAG 스케줄러 -> 자원 관리자 -> 작업 실행 서버(임시 저장소) -> 인코딩된 비디오

 

비디오는 GOP(Group of Pictures)로 불리는 단위로 쪼개서 핸들링. 각각의 방식은 책에서 확인(정리하긴 너무 김)

 

시스템 최적화

- 속도 최적화

1. 비디오 병렬 업로드(GOP로 쪼개서 업로드)

2. 업로드 센터를 사용자 근거리 지정

3. 모든 프로세스를 병렬로 처리

 

- 안정성 최적화

1. S3의 pre-signed URL로 클라이언트가 업로드하게 함

2. 비디오 보호(저작권 관리, 암호화, 워터마크 필요)

 

- 비용 최적화 

비디오는 롱테일 분포를 따른다. 인기있는 비디오만 빈번히 재생된다. 

1. 인기 비디오만 CDN에서 재생하고 다른 비디오는 다른 서버를 이용하도록 처리

2. 인기 없는 비디오는 인코딩도 하지 않음, 짧은 비디오는 필요할 때만 인코딩하도록 처리

3. 특정 지역에만 인기 있는 비디오는 특정 지역의 CDN에만 위치하도록

4. CDN 직접 구축 후 ISP와 연동(말이됨?)

 

오류 처리

적절한 리트라이와 오류 코드를 내려주기

 

사실 가장 관심있는건 비용 최적화였다.

 

그런데 비용 최적화를 철저하게 정책으로 대응한다는게 신기했다.

 

어차피 지연을 발생시키지 않으려면, 무조건 CDN을 사용해야하기 때문이지 않을까? 싶다.

 

비디오 트랜스코딩에 대해 너무 자세히 다뤘는데, 솔직히 기억하기 어려울 것 같다.

 

15장. 구글 드라이브 설계

개략적 추정치 

1. 가입자 오천만명, DAU 천만명

2. 모든 사용자에게 10GB 무료 저장공간 할당

3. 매일 각 사용자가 파일 2개를 업로드

4. 읽기:쓰기 비율 1:1

5. 필요한 사용 공간 : 5천만 x 10GB = 500페타바이트

등등

 

필요한 API

1. 파일 업로드 API : 단순 업로드, 이어 올리기

2. 파일 다운로드 API

3. 파일 갱신 히스토리 API 

 

저장소는 이리저리 고려해서 S3로 선택

파일의 동기화 충돌도 중요한 이슈라 충돌 방지를 위해 어떤 전략을 세울지 필요함. 

예시로 로컬 사본을 만들어 각각의 파일을 분리해서 저장하고, 어떻게 합칠지를 생각해봐야함

 

상세 설계에서 특이한 점은 블록 저장소다.

하나의 파일을 수정할 때 매번 전체 파일을 주고 받으면 리소스 낭비가 크기 때문에, 파일을 블록으로 나누어 저장하고 요청한 부분만 전달하고 수정하며 사용한다.

그리고 높은 일관성이 필요하다. 관계형 데이터 베이스를 써서 강한 일관성을 보장할지 NoSQL을 써서 결과적 일관성을 보장할지 요구 사항에 대응해야하는 부분이다.

 

알림서비스, 장애처리를 위한 파이프라인은 그렇게 특이한 점이 없었다.

 

고려할게 생각보다 별로 없다는 생각이 들 정도로 짧은 챕터였다. 생각해보면 동기화 문제 말고는 큰 이슈가 없어보이긴 하다. 저장소를 S3로 쓰면서 생각해야될 부분이 많이 줄긴할 것이다.

16장. 배움은 계속된다

끝!

 

마치며

책 요약을 이런 식으로 하니까 시간이 너무 오래걸린다.

 

한번 쭉 읽고, 포스팅을 하면서 다시한번 복기하니까 확실히 남는 건 있는 것 같지만 이런 식으로 쓰는 횟수를 줄이거나

 

독후감? 후기?를 간단하게 남기는 방식으로 작성할 것 같다.

 

이번 책은 현재 내 상황에서 경험해보기 힘든 정말 "초" 대규모 단위를 잘 버티기 위한 작업들을 다뤄서 너무 재미있게 읽었다.

 

보다보니 이 책의 내용을 기반으로 직접 구현한 사람들도 있던데 기회가 되면 한번 해보고싶긴하다.

 

그리고 AWS가 비싸긴하지만 쓰는 이유가 있다는 걸 다시한번 깨달았다.

 

 

 

참고 자료

https://velog.io/@jihoson94/%EA%B7%A0%EB%93%B1%ED%95%9C-%EB%B6%84%EB%B0%B0%EB%A5%BC-%EC%9C%84%ED%95%9C-%EA%B8%B0%EC%88%A0-%EC%95%88%EC%A0%95-%ED%95%B4%EC%8B%9C

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함