구글 드라이브 같은 파일 저장소 시스템을 설계하려고 하는데, 친한 백엔드 친구에게 물어보더니 S3를 쓴다는 전개는... 뭐랄까 좀 어이없었달까... 암튼 그랬다 ㅋㅋ ( 역시 클라우드의 왕 AWS )
신박한 것들이 많았는데, 특히 파일을 블록 단위로 나눠서 암호화해 업로드 하는 방식이 신기했다.
업로드된 파일을 여러 사용자가 편집할 때 (구글 드라이브는 공유 기능이 있으니까) 이거 싱크는 어떻게 맞추는가 궁금했는데 그런 내용이 안나와서 아쉬웠다.
드디어 두 번째 스터디도 끝!! 다들 고생하셨습니다 🎉
궁금한 점
시퀀셜 다이어그램을 보여주면서 업로드 시나리오를 보여주는데, 메타데이터의 업데이트와 파일 업로드를 각각 ( 아마 각각 다른 API를 요청하지 않으려나 ) 병렬로 요청하는데, 그럼 만약 파일 업로드가 실패하게 되면 메타데이터 업데이트도 롤백 되어야하고 알림도 가면 안되는데 이런 트랜잭션은 어떻게 보장할 수 있을까?
로드밸런서의 장애는 생각해본 적 없었는데 ( 왜 이 컴포넌트가 장애날 것이라곤 생각해본 적 없었을까... ㅋㅋ ) Second LB의 존재를 처음 알게 되서 신기했다. 이런 셋팅이 되어있는 플랫폼이 있으신지..? (궁금)
디스크 용량을 여러 서버에 나눠서 저장하는 샤딩 기법에 대한 이야기가 나왔는데, 이 마저도 뭔가 샤딩 서버들 용량이 꽉 차면 이슈가 생길 것 같다는 생각이 들었다. 더 좋은 방법이 없으려나?
이어 올리기 : 파일 사이즈가 크고, 네트워크 문제로 업로드가 중단될 가능성이 높다고 생각되면 사용한다.
이어 올리기 URL 을 받기 위한 최초 요청 전송
데이터를 업로드하고 업로드 상태 모니터링
업로드에 장애가 발생하면 장애 발생시점부터 업로드를 재시작
파일 다운로드 API
파일 갱신 히스토리 API
한 대 서버의 제약 극복
가장 먼저 떠오르는 해결책은 데이터를 샤딩하여 여러 서버에 나누어 저장하는 것
S3 사용 : 다중화 지원, 같은 리전 안에서 다중화 / 여러 리전에 걸쳐 다중화 가능
로드 밸런서
웹 서버 추가
메타데이터 DB : DB를 파일 저장 서버에서 분리하여 SPOF 를 회피, 아울러 다중화 및 샤딩 정책을 적용하여 가용성과 규모 확장성 요구사항 대응
파일 저장소 : S3 사용, 가용성과 데이터 무손실을 보장하기 위해 두 개 이상의 지역에 데이터 다중화
동기화 충돌
먼저 처리되는 변경은 성공한 것으로 보이고, 나중에 처리되는 변경은 충돌이 발생한 것으로 표시
오류가 발생한 시점에 이 시스템에는 같은 파일의 두 가지 버전이 존재하게 된다.
사용자 2가 가지고 있는 로컬 사본과 서버에 있는 최신 버전, 이 상태에서 사용자는 두 파일을 하나로 합칠지 아니면 둘 중 하나를 다른 파일로 대체할지를 결정해야 한다.
개략적 설계안
블록 저장소 서버 : 파일 블록을 클라우드 저장소에 업로드하는 서버다. 블록 저장소는 블록 수준 저장소라고도 하며, 클라우드 환경에서 데이터 파일을 저장하는 기술이다. 이 저장소는 파일을 여러 개의 블록으로 나눠 저장하며, 각 블록에는 고유한 해시값이 할당된다. 이 해시값은 메타 DB에 저장된다. 각 블록은 독립적인 객체로 취급되며 S3 에 보관된다.
클라우드 저장소
아카이빙 저장소 : 오랫동안 사용되지 않은 비활성 데이터를 저장하기 위한 컴퓨터 시스템
로드 밸런서
API 서버
메타데이터 DB : 사용자, 파일, 블록, 버전 등의 메타데이터 정보를 관리, 실제 파일은 클라우드에 보관
메타데이터 캐시
알림 서비스 : pub/sub 프로토콜 기반 시스템
오프라인 사용자 백업 큐 : 클라이언트가 접속 중이 아니라서 파일의 최신 상태를 확인할 수 없을 때는 해당 정보를 큐에 두어 나중에 클라이언트가 접속했을 때 동기화할 수 있도록 한다.
블록 저장소 서버
정기적으로 갱싱되는 큰 파일들은 업데이트가 일어날 때마다 전체 파일을 서버로 보내면 네트워크 대역폭을 많이 잡아먹게 된다. 최적화 방안은?
델타 동기화 : 파일이 수정되면 전체 파일 대신 수정이 일어난 블록만 동기화
압축 : 블록 단위로 압축해두면 데이터 크기를 많이 줄일 수 있다. 텍스트 파일을 압축할 때는 gzip, bzip2, 이미지나 비디오를 압축할 때는 다른 압축 알고리즘
파일을 블록 단위로 분할 → 압축 알고리즘 적용 → 암호화, 아울러 전체 파일으 저장소 시스템으로 보내는 대신 수정된 블록만 전송해야 한다.
strong consistency
메모리 캐시는 보통 최종 일관성 모델 지원
캐시에 보관된 사본과 DB 에 있는 원본 일치
DB에 보관된 원본에 변경이 발생하면 캐시에 있는 사본을 무효화한다.
업로드 절차 : 파일 메타데이터 추가 요청, 파일 업로드 요청이 병렬적으로 전송된 상황
파일 메타데이터 추가
클라이언트 1이 새 파일의 메타데이터를 추가하기 위한 요청 전송
새 파일의 메타데이터를 DB에 저장하고 업로드 상태를 대기중으로 변경
새 파일이 추가되었음을 알리는 알림 서비스에 통지
알림 서비스는 관련된 클라이언트(2) 에게 파일이 업로드 중이라는 것을 알림
파일을 클라우드 저장소에 업로드
클라이언트 1이 파일을 블록 저장소 서버에 업로드
블록 단위 분할 → 압축 → 암호화 → S3 전송
업로드 끝나면 클라우드 스토리지는 완료 콜백, 이 호출은 API 서버로 전송
메타데이터 DB에 기록된 파일 상태를 완료로 변경
알림 서비스에 파일 업로드가 끝났음을 통지
알림 서비스는 클라이언트(2) 에게 파일 업로드가 끝났음을 알림
다운로드 절차
파일 다운로드는 파일이 새로 추가되거나 편집되면 자동으로 시작된다. 어떻게 알지?
클라이언트 A가 접속 중이고 다른 클라이언트가 파일을 변경하면 알림 서비스가 클라이언트A 에게 변경이 발생했으니 새 버전을 끌어가야 한다고 알린다.
클라이언트 A가 네트워크에 연결된 상태가 아닌 경우, 데이터는 캐시에 보관, 해당 클라이언트의 상태가 접속중으로 바뀌면 그때 해당 클라이언트는 새 버전을 가져갈 것
알림 서비스
파일의 일관성을 유지하기 위해, 클라이언트는 로컬에서 파일이 수정되었음을 감지하는 순간 다른 클라이언트에 그 사실을 알려서 충돌 가능성을 줄여야 한다.
롱 폴링 사용 : 각 클라이언트는 알림 서버와 롱 폴링 연결을 유지, 특정 파일에 대한 변경을 감지하면 해당 연결을 끊는다. 이 때 클라이언트는 반드시 메타데이터 서버와 연결해 파일의 최신 내역을 다운로드, 해당 다운로드 작업이 끝났거나, timeout 시간에 도달한 경우 즉시 새 요청을 보내 롱 폴링 연결 복원
저장소 공간 절약
중복 제거 : 중복된 파일 블록을 계정 차원에서 제거, 해시 값 비교를 통해 판단
지능적 백업 전략
한도 설정 : 보관해야 하는 파일 버전 개수에 상한을 두는 것
중요한 버전만 보관
자주 쓰이지 않는 데이터는 아카이빙 저장소로 옮긴다. 아마존 S3 글래시어
장애 처리
로드 밸런서 장애 : 부 로드밸런서가 활성화되어 트래픽을 이어 받아야 한다. 로드 밸런서끼리는 보통 heartbeat 신호를 주기적으로 보내서 상태를 모니터링한다.
블록 저장소 서버 장애 : 블록 저장소 서버에 장애가 발생하였다면 다른 서버가 미완료 상태 또는 대기 상태인 작업을 이어 받아야 한다.
S3 장애 : 다중화
API 서버 장애 : 로드 밸런서가 트래픽 해당 서버로 보내지 않음으로써 장애 격리
메타데이터 캐시 장애 : 캐시 서버 다중화
메타데이터 DB 장애 : slave DB 를 master DB 로 바꾸고 slave DB 추가
알림 서비스 장애 : 한 대의 드롭박스 알림 서비스 서버가 관리하는 연결의 수 백만 개가 넘음. 따라서 한 대의 서버에 장애가 발생하면 백만 명 이상의 사용자가 롱 폴링 연결을 다시 만들어야 한다. 주의할 것은 한 대 서버로 백만 개 이상의 접속을 유지하는 것은 가능하지만, 동시에 백만 개 접속을 시작하는 것은 불가능하다는 점. 따라서 롱 폴링 연결을 복구하는 것은 상대적으로 느릴 수 있다.
느낀점
궁금한 점
요약
uploadType=media
)uploadType=multipart
)uploadType=resumable
)