•
구글 드라이브, 드롭박스 등 클라우드 저장소 서비스는 최근 높은 인기를 가지는 클라우드 서비스 중 하나다.
•
대표적인 구글 드라이브 서비스가 어떤 서비스인지 알아보자.
◦
구글 드라이브는 파일 저장 및 동기화 서비스로 문서, 사진, 비디오, 기타 파일을 클라우드에 보관할 수 있어야 한다.
◦
이 파일들은 컴퓨터, 스마트폰 그 어떤 단말에서도 이용 가능해야 한다.
1단계 문제 이해 및 설계 범위 확정
•
질문을 통해 설계 범위를 결정해보자.
◦
가장 중요하게 지원해야 할 기능이 무엇인지
◦
모바일 앱과 웹 앱 가운데 하나만 지원하는지, 아니면 둘 다 지원해야 하는지
◦
파일을 암호화해야하는지
◦
파일 크기에 제한이 있는지
◦
사용자가 얼마나 되는지
•
이런 기능적 요구사항 외에도 다음의 비-기능적 요구사항을 이해하는 것도 중요하다.
◦
안정성, 빠른 동기화 속도, 네트워크 대역폭, 규모 확장성, 높은 가용성
개략적 추정치
•
가입 사용자는 오천만 명이고 천만 명의 DAU 사용자가 있다고 가정
•
모든 사용자에게 10GB의 저장공간을 무료로 할당
•
매일 각 사용자가 평균 2개의 파일을 업로드한다고 가정, 각 파일의 평균 크기는 500 kB
•
읽기:쓰기 비율은 1:1
•
이를 통해 필요한 저장공간 총량을 계산해보면 5천만 사용자 * 10GB = 500페타바이트
•
업로드 API QPS는 1천만 사용자 * 평균 2회 업로드 / 24 h / 3600 s = 대략 240
•
최대 QPS는 2배인 480을 임의로 설정한다.
2단계 개략적 설계안 제시 및 동의 구하기
•
기존의 설계법과는 달리, 이번에는 모든 것을 담은 하나의 서버에서 출발해 점진적으로 천만 사용자를 지원하는 시스템으로 발전시켜나간다.
•
우선 아래와 같은 구성의 서버 한 대로 시작한다.
◦
파일을 올리고 다운로드하는 과정을 처리하는 웹 서버
◦
사용자 데이터, 로그인 정보, 파일 정보 등의 메타데이터를 보관할 데이터베이스
◦
파일을 저장할 저장소 시스템, 파일 저장을 위해 1TB의 공간을 사용
API
•
다음 세 종류의 API를 제공해야 한다.
◦
파일 업로드 API : 단순 업로드, 이어 올리기의 업로드를 지원해야 한다.
◦
파일 다운로드 API : 다운로드할 파일의 경로를 가지고 다운로드를 제공해야 한다.
◦
파일 갱신 히스토리 API : 갱신 히스토리를 가져올 파일의 경로와 히스토리 길이의 최대치를 가지고 히스토리를 조회한다.
한 대의 서버의 제약 극복
•
업로드되는 파일이 많아지다보면 결국 파일 시스템의 물리적 공간의 제약으로 인해 한계가 찾아오게 된다.
◦
이 경우, 데이터를 샤딩하여 분산 저장하는 방법이 가장 먼저 떠오를 것이다. 혹은 S3와 같은 객체 저장소 서비스를 사용하여 개선할 수 있다.
•
네트워크 트래픽이 과도하게 몰려, 자원이 고갈되는 이슈가 발생할 수 있다.
◦
이는 로드밸런서를 사용해 해결을 시도할 수 있다. 또한 로드밸런서를 사용하면 웹 서버를 아주 쉽게 추가할 수 있다.
•
데이터베이스 역시, 하나의 서버에서 처리되는 경우, 결국 한계에 도달할 것이다.
◦
이를 기존 서버와 분리하여 독립적인 데이터베이스 서버로 두었다가 요청량이 증가함에 따라 샤딩, 다중화를 적용하여 가용성과 규모 확장성 요구사항에 따라 대응한다.
개략적 설계안
•
사용자 단말 : 사용자가 이용하는 웹 브라우저나 모바일 앱 등의 클라이언트
•
블록 저장소 서버 : 파일 블록을 클라우드 저장소에 업로드하는 서버, 블록 저장소는 블록 수준 저장소라고도 하며 클라우드 환경에서 데이터 파일을 저장하는 기술이다.
◦
이 저장소는 파일을 여러 개의 블록으로 나눠 저장하며 각 블록에는 고유한 해시값이 할당되고, 이는 메타데이터 데이터베이스에 저장된다.
•
클라우드 저장소 : 파일은 블록 단위로 나눠져 클라우드 저장소에 보관된다.
•
아카이빙 저장소 : 오랫동안 사용되지 않은 비활성 데이터를 저장하기 위한 컴퓨터 시스템이다.
•
로드밸런서 : 요청을 모든 API 서버에 고르게 분산하는 역할을 수행한다.
•
API 서버 : 파일 업로드 외에 거의 모든 기능을 담당하며 사용자 인증, 프로필 관리, 파일 메타데이터 갱신 등을 처리한다.
•
메타데이터 데이터베이스 : 사용자, 파일, 블록, 버전 등의 메타데이터 정보를 관리한다.
•
메타데이터 캐시 : 성능을 높이기 위해 자주 쓰이는 메타데이터를 캐시해둔다.
•
알림 서비스 : 특정 이벤트가 발생했음을 클라이언트에게 알리는데 사용한다.
•
오프라인 사용자 백업 큐 : 클라이언트가 접속 중이 아닌 경우, 접속했을 때 동기화가 처리되도록 한다.
3단계 상세 설계
블록 저장소 서버
•
정기적으로 갱신되는 파일들이, 업데이트가 일어날 때마다 전체 파일을 서버로 보내면 네트워크 대역폭을 많이 잡아먹게 된다. 이를 최적화하는 방법으로는 다음 두 가지 정도를 생각해볼 수 있다.
◦
델타 동기화 : 파일이 수정되면 전체 파일 대신 수정이 일어난 블록만 동기화한다.
◦
압축 : 블록 단위로 압축해 두면 데이터 크기를 많이 줄일 수 있고, 압축 알고리즘은 파일 유형에 따라 정한다.
•
이 시스템은 블록 저장소 서버는 파일 업로드에 관계된 일을 처리하는 컴포넌트다.
높은 일관성 요구사항
•
이런 시스템은 보통 같은 파일이 단말이나 사용자에 따라 다르게 보이는 것이 적절하지 못하므로 강한 일관성 모델을 기본으로 지원해야 한다.
•
메모리 캐시는 보통 최종 일관성 모델을 지원한다. 따라서 강한 일관성을 달성하려면 다음 사항을 보장해야 한다.
◦
캐시에 보관된 사본과 데이터베이스에 있는 원본이 일치한다.
◦
데이터베이스에 보관된 원본에 변경이 발생하면 캐시에 있는 사본을 무효화한다.
•
관계형 데이터베이스는 ACID를 보장하므로 강한 일관성을 보장하기 쉽다. 하지만 NoSQL은 이를 기본적으로 지원하지 않으므로 동기화 로직 안에 프로그램해 넣어야 한다.
업로드 절차
•
파일 메타데이터 추가
1.
클라이언트 1이 새 파일의 메타데이터를 추가하기 위한 요청 전송
2.
새 파일의 메타데이터를 데이터베이스에 저장하고 업로드 상태를 대기중으로 변경
3.
새 파일이 추가되었음을 알림 서비스에 통지
4.
알림 서비스는 관련된 클라이언트에게 파일이 업로드되고 있음을 알림
•
파일을 클라우드 저장소에 업로드
1.
클라이언트 1이 파일을 블록 저장소 서버에 업로드
2.
블록 저장소 서버는 파일을 블록 단위로 쪼갠 다음 압축하고 암호화 한 다음 클라우드 저장소에 전송
3.
업로드가 끝나면 클라우드 스토리지는 완료 콜백을 호출, 이 콜백 호출은 API 서버로 전송됨
4.
메타데이터 DB에 기록된 해당 파일의 상태를 완료로 변경
5.
알림 서비스에 파일 업로드가 끝났음을 통지
6.
알림 서비스는 관련된 클라이언트에게 파일 업로드가 끝났음을 알림
다운로드 절차
1.
알림 서비스가 클라이언트 2에게 누군가 파일을 변경했음을 알림
2.
알림을 확인한 클라이언트 2는 새로운 메타데이터를 요청
3.
API 서버는 메타데이터 데이터베이스에게 새 메타데이터 요청
4.
API 서버에게 새 메타데이터가 반환됨
5.
클라이언트 2에게 새 메타데이터가 반환됨
6.
클라이언트 2는 새 메타데이터를 받는 즉시 블록 다운로드 요청 전송
7.
블록 저장소 서버는 클라우드 저장소에서 블록 다운로드
8.
클라우드 저장소는 블록 서버에 요청된 블록 반환
9.
블록 저장소 서버는 클라이언트에게 요청된 블록 반환, 클라이언트 2는 전송된 블록을 사용하여 파일 재구성
알림 서비스
•
파일의 일관성을 유지하기 위해, 로컬에서 파일이 수정됨을 감지하는 순간, 다른 클라이언트에게 해당 사실을 알려, 충돌 가능성을 고지해야 한다.
•
알림 서비스는 이런 목적으로 사용되는데, 단순하게, 이벤트 데이터를 클라이언트로 보내는 서비스다.
◦
따라서 이를 구현하기 위해서는 롱 폴링, 웹소켓 정도의 선택지가 있다.
저장소 공간 절약
•
비용 절감을 위해, 보통 아래 세 가지 방벙 정도가 있다.
◦
중복 제거
◦
지능적 백업 전략 도입
▪
한도 설정, 중요 버전만 보관
◦
자주 쓰이지 않는 데이터는 아카이빙 저장소로
장애 처리
•
이 역시, 각 지점별로 장애가 발생할 수 있는 소지들에 대해서 충분한 처리가 있어야 한다.
4단계 마무리
•
추가적으로 고민해볼만한 부분은 다음과 같다.
◦
블록 저장소 서버를 거치지 않고 파일을 바로 클라우드 저장소에 저장하는 방법
◦
접속상태를 관리하는 기능을 별도 서비스로 옮기는 것