Read Book/대규모 시스템 설계 기초

15장. 구글 드라이브 설계

nowwater 2023. 9. 12. 22:03
728x90

구글 드라이브

  • 파일 저장 및 동기화 서비스로, 문서, 사진, 비디오, 기타 파일을 클라우드에 보관할 수 있도록 한다.
  • 컴퓨터, 스마트폰, 태블릿 등 어떤 단말에서도 이용 가능해야 한다.
  • 보관된 파일은 친구, 가족, 동료 들과 손쉽게 공유할 수 있어야 한다.

 

제공 API

1. 파일 업로드 API

단순 업로드: 파일 크기가 작을 때 사용

이어 올리기: 파일 사이즈가 크고 네트워크 문제로 업로드가 중단될 가능성이 높은 경우 사용

  • 이어 올리기 URL 을 받기 위한 최초 요청 전송
  • 데이터를 업로드하고 업로드 상태 모니터링
  • 업로드에 장애 발생 시 장애 발생시점부터 업로드를 재시작

2. 파일 다운로드 API

3. 파일 갱신 히스토리 API

 

위 API 모두 사용자 인증을 필요로 하고, HTTPS 프로토콜을 사용해야 한다.

SSL 을 지원하는 프로토콜을 이용하는 이유는, 클라이언트와 백엔드 서버가 주고받는 데이터를 보호하기 위한 것

 

한 대 서버의 제약 극복

업로드되는 파일이 많아지다 보면 결국엔 파일 시스템이 가득 차게 됨

긴급히 문제를 해결해야 하는데, 가장 먼저 떠오르는 해결책은 데이터를 샤딩하여 여러 서버에 나누어 저장하는 것

그러나 샤딩 이후에도 특정 서버에 장애가 생기면 데이터를 읽게 될 수도 있는데, 이를 방지하기 위해 클라우드 데이터 저장소(e.g. 아마존 S3) 를 이용할 수 있다.

이를 통해 다중화도 쉽게 할 수 있고, 특히 여러 지역에 다중화를 한다면 데이터 손실을 막고 가용성을 최대한으로 보장할 수 있다.

 

추가적으로 개선이 가능한 부분은 다음과 같다.

  • 로드밸런서: 네트워크 트래픽을 고르게 분산하여, 특정 웹 서버 장애 시 자동으로 해당 서버를 우회시킨다.
  • 웹 서버: 로드밸런서를 이용해 요청을 처리할 웹 서버를 손쉽게 추가할 수 있어 폭증하는 트래픽에 쉽게 대응 가능
  • 메타데이터 데이터베이스: 데이터베이스를 파일 저장 서버로부터 분리하여 SPOF 를 회피, 다중화 및 샤딩 정책을 적용해 가용성과 규모 확장성 요구사항에 대응
  • 파일 저장소: S3 파일 저장소 사용하고, 가용성과 데이터 무손실을 보장하기 위해 여러 지역에 데이터를 다중화

 

 

동기화 충돌

두 명 이상의 사용자가 같은 파일이나 폴더를 동시에 업데이트하려고 하는 경우 충돌이 발생할 수 있다.

여기서는 먼저 처리되는 변경은 성공으로 보고, 나중에 처리되는 변경은 충돌이 발생한 것으로 표시하여 충돌을 해소하는 방법을 사용한다.

오류가 발생한 시점에 시스템에는 같은 파일의 두 가지 버전이 존재하게 된다.

두 파일을 하나로 합칠지, 아니면 둘 중 하나를 다른 파일로 대체할지를 결정해야 한다.

 

개략적 설계안

  • 사용자 단말: 웹브라우저, 모바일 앱 등의 클라이언트
  • 블록 저장소 서버(block server): 파일 블록을 클라우드 저장소에 업로드하는 서버
    • 블록 저장소: 클라우드 환경에서 데이터 파일을 저장하는 기술
    • 파일을 여러 블록으로 나눠 저장하며, 각 블록에는 고유한 해시값이 할당됨
    • 해시값은 메타데이터 데이터베이스에 저장된다.
    • 각 블록은 독립적인 객체로 취급되며 클라우드 저장소 시스템에 보관됨
    • 파일을 재구성하려면 블록들을 원래 순서대로 합쳐야 함
  • 클라우드 저장소: 블록 단위로 나눠진 파일을 클라우드 저장소에 보관
  • 아카이빙 저장소: 오랫동안 사용되지 않은 비활성 데이터를 저장하기 위한 컴퓨터 시스템
  • 로드밸런서: 요청을 모든 API 서버에 골고루 분산
  • API 서버: 파일 업로드 외 모든 기능 담당하는 서버. 사용자 인증, 사용자 프로파일 관리, 파일 메타데이터 갱신 등
  • 메타데이터 데이터베이스: 사용자, 파일, 블록, 버전 등의 메타데이터 정보를 관리(오직 메타데이터만)
  • 메타데이터 캐시: 성능을 높이기 위해 자주 쓰이는 메타데이터는 캐시
  • 알림 서비스: 클라이언트에게 파일이 추가되었거나, 편집되었거나, 삭제되었음을 알려 파일의 최신 상태를 확인하도도록 해줌
  • 오프라인 사용자 백업 큐: 클라이언트가 접속 중이 아닌 경우 파일변경 정보를 이 큐에 두어 나중에 클라이언트가 접속했을 때 동기화가 될 수 있도록 함.

 

상세 설계

블록 저장소 서버

정기적으로 갱신되는 큰 파일들은 업데이트가 일어날 때마다 전체 파일을 서버로 보내면 네트워크 대역폭을 많이 잡아먹게 된다. 따라서 다음 2가지 방법으로 최적화할 수 있다.

 

델타 동기화

파일이 수정되면 전체 파일 대신 수정이 일어난 불록만 동기화

 

압축

블록 단위로 압축해 두면 데이터 크기를 많이 줄일 수 있다. 압축 알고리즘은 파일 유형에 따라 정함

 

블록 저장소 서버는 파일 업로드에 관계된 힘든 일을 처리하는 컴포넌트다.

  • 주어진 파일을 작은 블록 단위로 나누기
  • 각 블록에 압축 알고리즘 적용
  • 클라우드 저장소로 보내기 전 암호화
  • 전체 파일을 저장소 시스템으로 보내는 대신 수정된 블록만 전송

델타 동기화 전략과 압축 알고리즘을 도입해 네트워크 대역폭 사용량을 절감할 수 있다.

 

높은 일관성 요구사항

드라이브를 설계할 때는 강한 일관성 모델을 기본으로 지원해야 한다. 즉, 같은 파일이 단말이나 사용자에 따라 다르게 보이는 것은 허용할 수 없다.

메모리 캐시는 보통 최종 일관성 모델을 지원하기에, 캐시에도 강한 일관성을 달성하려면 다음 사항을 보장해야 한다.

  • 캐시에 보관된 사본과 데이터베이스에 있는 원본이 일치
  • 데이터베이스에 보관된 원본에 변경이 발생하면 캐시에 있는 사본을 무효화

관계형 데이터베이스는 ACID 를 보장하기에 강한 일관성을 보장하기 쉬운 반면, NoSQL 데이터베이스는 이를 기본으로 지원하지 않으므로, 동기화 로직 안에 프로그램해 넣어야 한다.

 

메타데이터 데이터베이스

드라이브를 설계하기 위해 필요한 단순화된 스키마 설계안

 

업로드 절차

두 개의 요청이 병렬로 전송된다.

  • 파일 메타데이터 추가
  • 파일을 클라우드 저장소에 업로드

 

다운로드 절차

파일이 새로 추가되거나 편집되면 자동으로 파일 다운로드가 시작된다.

다른 클라이언트가 파일을 편집하거나 추가했다는 사실을 감지하는 방법은 2가지가 있다.

  • 온라인일 경우 알림 서비스로 알림: A 클라이언트가 접속 중일 때 다른 클라이언트가 파일 변경 시 알림 서비스가 A 클라이언트에게 변경이 발생했으니 새 버전을 끌어가야 한다고 알린다.
  • 오프라인일 경우 캐시 보관: 네트워크에 연결된 상태가 아닐 경우 데이터는 캐시에 보관, 온라인이 되면 그때 새 버전을 가져감

 

알림 서비스

파일 수정 감지 시 다른 클라이언트에 그 사실을 알려서 충돌 가능성을 줄이기 위한 목적으로 사용

 

구현 방식

  • 롱 폴링
  • 웹소켓

드라이브 설계 시에는 양방향 통신이 불필요하므로, 롱 폴링 방식으로 구현

  • 접속 중인 유저는 알림 서버와 롱 폴링 연결을 하나씩 유지한다.
  • 각 클라이언트는 알림 서버와 롱 폴링용 연결을 유지하다가, 특정 파일의 변경을 감지하면 해당 연결을 끊는다. 이때 클라이언트는 반드시 메타데이터 서버와 연결해 파일의 최신 내역을 다운로드 해야 한다.
  • 해당 다운로드 작업이 끝났거나 연결 타임아웃 시간에 도달한 경우에는 즉시 새 요청을 보내어 롱 폴링 연결을 복원하고 유지해야 한다.

 

저장소 공간 절약

파일 갱신 이력을 보존하고 안정성을 보장하기 위해서는 파일의 여러 버전을 여러 데이터센터에 보관할 필요가 있다.

그 상황에서 모든 버전을 자주 백업하게 되면 저장용량이 너무 빨리 소진될 가능성이 있다.

따라서 이런 문제를 피하고 비용 절감을 위해 아래 세 가지 방법을 사용

  • 중복 제거: 계정 차원에서 중복된 파일 블록을 제거
  • 지능적 백업 전략 도입
    • 한도 설정: 보관해야 하는 파일 버전 개수에 상한
    • 중요한 버전만 보관: 불필요한 버전과 사본이 만들어지는 것을 피하기 위해 중요한 것만 골라내 보관
  • 아카이빙 저장소: 자주 쓰이지 않는 데이터는 따로 보관

 

장애 처리

로드밸런서 장애

부 로드밸런서 활성화시켜 트래픽 이어 받기

로드밸런서들끼리는 보통 하트비트 신호를 주기적으로 보내 상태를 모니터링함

 

블록 저장소 서버 장애

다른 서버가 미완료/대기 상태인 작업을 이어받음

 

클라우드 저장소 장애

여러 지역에 다중화

 

API 서버 장애

로드밸런서를 통해 장애가 난 서버에 트래픽을 보내지 않도록 하여 격리시킴

 

메타데이터 캐시 장애

마찬가지로 다중화

 

메타데이터 데이터베이스 장애

주 데이터베이스 서버 장애: 부 데이터베이스 서버 중 하나를 주 서버로, 부 데이터베이스 서버 새로 하나 추가

부 데이터베이스 서버 장애: 다른 부 데이터베이스 서버가 읽기 연산 처리, 그동안 장애 서버는 새 것으로 교체

 

알림 서비스 장애

장애 발생 시 새로 롱 폴링 연결을 만들어야 함

한 대 서버로 백만 개 이상의 접속을 유지하는 것은 가능하지만, 동시에 백만 개 접속을 시작하는 것은 불가

따라서 롱 폴링 연결을 복구하는 것은 상대적으로 느릴 수 있다.

 

오프라인 사용자 백업 큐 장애

마찬가지로 다중화

큐에 장애 발생 시 구독 중인 클라이언트들은 백업 큐로 구독 관계를 재설정

 

정리

1. 파일의 메타데이터 관리

업로드 시 메타데이터 저장, 파일 업로드 병렬 처리

 

2. 파일 동기화 처리

온라인 유저: 롱 폴링으로 변경 감지 이후, 메타 데이터 변경 이력 조회 및 파일 다운로드 시도(동기화)

오프라인 유저: 백업 큐, 캐시를 활용해 변경 내역 보관, 이후 접속 시 동기화 수행