14장.유튜브 설계
1단계 설계 범위 확정
요구사항
- 빠른 비디오 업로드
- 원활한 비디오 재생
- 재생 품질 선택 기능
- 낮은 인프라 비용
- 높은 가용성과 규모 확장성 그리고 안정성
- 지원 클라이언트: 모바일 앱, 웹 브라우저 그리고 스마트 TV
개략적 규모 추정
- 일간 능동 사용자 수는 5백만
- 사용자 한 명은 하루에 평균 5개의 비디오를 시청
- 10%의 사용자가 하루에 비디오 한 개 업로드
- 비디오 평균 크기는 300MB
- 비디오 저장을 위해 매일 새로 요구되는 저장 용량 = 5백만 * 10% * 300MB = 150TB
- CDN 비용
- CDN에서 나가는 데이터의 양에 따라 과금한다.
- 해당 비용을 줄이는 방향으로 설계 진행
2단계 개략적 설계안
기존 클라우드 서비스를 이용해도 좋다.
- 주어진 시간 안에 적절한 기술을 골라 설계를 마치는 것이 중요하다.
- BLOB 저장소나 CDN을 만드는 것은 복잡하고 많은 비용이 드는 일이다.
개략적으로 설계하는 시스템은 세 개 컴포넌트로 구성 된다.
- 단말(client): 컴퓨터, 모바일 폰, 스마트 TV 를 통해서 시청할 수 있다.
- CDN: 비디오는 CDN에 저장한다. 재생 버튼을 누르면 CDN으로부터 스트리밍이 이루어진다.
- API 서버: 비디오 스트리밍을 제외한 모든 요청은 API 서버가 처리한다.
면접관이 아래 두 영역을 설계해 줄 것을 요청
- 비디오 업로드 절차
- 비디오 스트리밍 절차
비디오 업로드 절차
- 사용자: 단말기를 통해 유튜브를 시청하는 이용자.
- 로드밸런서: API 서버 각각으로 고르게 요청을 분산하는 역할
- API 서버: 비디오 스트리밍을 제외한 다른 모든 요청을 처리
- 메타데이터 데이터베이스: 비디오의 메타데이터를 보관, 샤딩과 다중화를 적용하여 성능 및 가용성 요구사항 충족
- 메타데이터 캐시: 성능을 높이기 위해 비디오 메타데이터와 사용자 객체는 캐시한다.
- 원본 저장소: 원본 비디오를 보관하는 대형 이진 파일 저장소(BLOB) 시스템.
- 트랜스코딩 서버: 비디오 트랜스코딩은 비디오 인코딩이라 부르기도 하는 절차로, 비디오의 포맷을 변환하는 절차. 단말이나 대역폭 요구사항에 맞는 최적의 비디오 스트림을 제공하기 위해 필요
- 트랜스코딩 비디오 저장소: 트랜스코딩이 완료된 비디오를 저장하는 BLOB 저장소
- CDN: 비디오를 캐시하는 역할을 담당. 사용자가 재생 버튼을 누르면 비디오 스트리밍은 CDN을 통해 이루어진다.
- 트랜스코딩 완료 큐: 비디오 트랜스코딩 완료 이벤트들을 보관할 메세지 큐.
- 트랜스코딩 완료 핸들러: 트랜스코딩 완료 큐에서 이벤트 데이터를 꺼내어 메타데이터 캐시와 데이터베이스를 갱신할 작업 서버
비디오 업로드가 병렬적으로 어떻게 수행되는지 확인
a. 비디오 업로드
b. 비디오 메타데이터 갱신
프로세스 a: 비디오 업로드
- 비디오를 원본 저장소에 업로드
- 트랜스코딩 서버는 원본 저장소에서 해당 비디오를 가져와 트랜스코딩을 시작
- 트랜스코딩이 완료되면 아래 두 절차가 병렬적으로 수행
3a. 완료된 비디오를 트랜스코딩 비디오 저장소로 업로드
3b.트랜스코딩 완료 이벤트를 트랜스코딩 완료 큐에 넣는다.
3a.1. 트랜스 코딩이 끝난 비디오를 CDN에 올린다.
3b.1. 완료 핸들러가 이벤트 데이터를 큐에서 꺼낸다.
3b.1.a, b1.1.b. 완료 핸들러가 메타데이터 데이터베이스와 캐시를 갱신한다. - API 서버가 단말에게 비디오 업로드가 끝나서 스트리밍 준비가 되었음을 알린다.
프로세스 b: 메타데이터 갱신
원본 저장소에 파일이 업로드되는 동안, 단말은 병렬적으로 비디오 메타데이터 갱신 요청을 API 서버에 보낸다.
해당 요청에 포함되는 메타 데이터는 파일 이름, 크기, 포맷 등의 정보가 있다.
API 서버는 해당 정보로 메타 데이터 캐시와 데이터베이스를 업데이트 한다.
비디오 스트리밍 절차
유튜브에서 비디오 재생 버튼을 누르면 스트리밍이 바로 시작된다.
스트리밍은 사용자의 장치가 원격지의 비디오로부터 지속적으로 비디오 스트림을 전송 받아 영상을 재생하는 것을 말한다.
비디오 스트리밍이 이루어지는 절차를 논하기전에 스트리밍 프로토콜 개념을 알아야한다.
- MPEG-DASH
- MPEG는 "Moving Picture Experts Group"의 약어
- DASH는 "Dynamic Adaptive Stream over HTTP"의 약어
- 애플 HLS(HTTP Live Stream)
- 마이크로소프트 스무드 스트리밍(Microsoft Smooth Streaming)
- 어도비 HTTP 동적 스트리밍(Adobe HTTP Dynamic Streaming, HDS)
프로토콜마다 지원하는 비디오 인코딩이 다르고 플레이어도 다르다.
서비스의 사용에 맞는 프로토콜을 잘 골라서 사용하자.
비디오는 CDN에서 바로 스트리밍된다.
사용자의 단말에 가장 가까운 CDN 에지 서버가 비디오 전송을 담당한다.
3단계 상세 설계
개략적 설계에서 비디오 업로드를 담당하는 부분과 비디오 스트리밍을 담당하는 부분을 나눠서 살펴봤고, 두 부분을 최적화 방안과 상세하게 소개한다.
비디오 트랜스 코딩
비디오를 녹화하면 단말(카메라, 휴대폰)은 비디오를 특정 포맷으로 저장하는데 다른 단말에서도 순조롭게 해당 영상이 재생되려면 호환되는 비트레이트(bitrate)와 포맷으로 저장되어야 한다.
비트레이트는 비디오를 구성하는 비트가 얼마나 빨리 처리되어야 하는지를 나타내는 단위.
비트레이트가 높은 비디오는 일반적으로 고화질이다.
비디오 트랜스코딩은 아래와 같은 이유로 중요
- 가공된지 않은 원본 비디오는 저장 공간을 많이 차지한다.
- 상당수의 단말과 브라우저는 특정 종류의 비디오 포맷만 지원.
=> 따라서 호환성 문제를 해결하기 위해 여러 포맷으로 인코딩해두는 것이 바람직하다. - 네트워크 대역폭이 충분하지 않은 사용자에게는 저화질 비디오를, 대역폭이 충분한 사용자에게는 고화질 비디오를 제공
- 모바일 단말의 경우 네트워크 상황이 수시로 달라진다. 자동으로 비디오 화질을 변경하거나 수동으로 변경할 수 있어야 한다.
인코딩 포맷 구성
- 컨테이너
- 비디오 파일, 오디오, 메타데이터를 담는 바구니 같은 것
- 컨테이너 포맷은 .avi, .mov, .mp4 같은 파일 확장자
- 코덱
- 비디오 화질은 보존하면서 파일 크기를 줄일 목적으로 고안된 압축 및 압축 해제 알고리즘
H.264, VP9, HEVC가 많이 사용된다.
- 비디오 화질은 보존하면서 파일 크기를 줄일 목적으로 고안된 압축 및 압축 해제 알고리즘
유향 비순환 그래프(DAG) 모델
비디오를 트랜스코딩하는 것은 컴퓨티 자원을 많이 소모하고 시간도 많이 드는 작업이다.
비디오 제작자는 워터마크, 섬네일 이미지, 화질 등 여러 유형의 비디오를 제작한다.
여러 유형의 비디오 프로세싱 파이프라인을 지원하는 한편 처리 과정의 병렬성을 높이기 위해서 적절한 수준의 추상화를 도입하여 클라이언트 프로그래머로 하여금 실행할 작업을 손수 정의할 수 있도록 해야한다.
페이스북의 스트리밍 비디오 엔진은 유향 비순환 그래프 프로그래밍 모델을 도입하여 작업을 단계별로 배열할 수 있도록 했고, 작업들을 순차적 또는 병렬적으로 실행할 수 있다.
원본 비디오는 비디오, 오디오, 메타데이터 세 부분으로 나누어서 처리된다.
- 검사: 좋은 품질의 비디오인지, 손상 없는지 확인
- 비디오 인코딩: 비디오를 다양한 해상도, 코덱, 비트레이트 조합으로 인코딩
- 섬네일: 사용자가 업로드한 이미지나 비디오에서 자동으로 추출된 이미지로 만드는 작업
- 워터마크: 식별정보를 이미지위에 오버레이 형태로 띄워 표시하는 작업
비디오 트랜스코딩 아키텍처
클라우드 서비스를 활용한 비디오 트랜스코딩 아키텍처를 정의
전처리기
아래와 같이 세 가지 일을 한다.
- 비디오 분할: 비디오 스트림을 GOP라고 불리는 단위로 쪼갠다.
GOP는 특정 순서로 배열된 프레임 그룹이다.
하나의 GOP는 독립적으로 재생 가능하며, 길이는 보통 몇 초 정도이다. - DAG 생성: 클라이언트는 프로그래머가 작성한 설정 파일에 따라 DAG를 만든다.
- 데이터 캐시: 전처리기는 분할된 비디오의 캐시이기도 하다.
안전성을 높이기 위해 GOP와 메타데이터를 임시저장소에 보관한다.
DAG 스케줄러
DAG 그래프를 몇 개 단계로 분할한 다음 각각을 자원 관리자의 작업 큐에 집어 넣는다.
아래 그림은 DAG 그래프를 2개 작업 단계로 쪼갠 사례
첫 번째 단계는 비디오, 오디오, 메타데이터를 분리
두 번째 단계는 비디오 파일을 인코딩하고 섬네일을 추출하며, 오디오 파일 또한 인코딩한다.
자원관리자
자원 배분을 효율적으로 수행하는 역할을 담당
세 개의 큐와 작업 스케줄러로 구성
- 작업 큐(task queue): 실행할 작업이 보관되어 있는 우선순위 큐
- 작업 서버 큐: 작업 서버의 가용 상태 정보가 보관되어 있는 우선순위 큐
- 실행 큐: 현재 실행 중인 작업 및 작업 서버 정보가 보관되어 있는 큐
- 작업 스케줄러: 최적의 작업/서버 조합을 골라, 해당 작업 서버가 작업을 수행하도록 지시하는 역할
작업 관리자는 아래와 같이 동작한다.
- 작업 큐에서 가장 높은 우선순위의 작업을 꺼낸다.
- 해당 작업을 실행하기 적합한 작업 서버를 고른다.
- 해당 작업 서버에게 작업 실행을 지시
- 해당 작업이 어떤 서버에게 할당되었는지에 관한 정보를 실행 큐에 넣는다.
- 작업이 완료되면 해당 작업을 실행 큐에서 제거한다.
작업 서버
작업 서버는 DAG에 정의된 작업을 수행한다.
작업 종류에 따라 작업 서버도 구분하여 관리한다.
임시 저장소
저장소 구현에는 여러 저장소 시스템을 활용할 수 있다. 어떤 시스템을 선택할 것인지는 저장할 데이터에 따라 달라진다.
메타데이터 작업의 경우에는 빈번히 참조하는 정보로 메모리에 캐시하면 좋다.
비디오/오디오 데이터는 BLOB 저장소에 두는 것이 바람직하다.
인코딩된 비디오
인코딩된 비디오는 인코딩 파이프라인의 최종 결과물이다.
시스템 최적화
속도, 안전성 그리고 비용 측면에서 시스템을 최적화하자.
속도 최적화: 비디오 병렬 업로드
비디오 전부를 한 번의 업로드에 올리는 것은 비효율적
작은 GOP들로 분리할 수 있다.
병렬적으로 업로드하면 일부가 실패해도 빠르게 업로드를 재개할 수 있다.
비디오를 GOP경계에 맞춰 분할하는 작업을 단말이 수행하면 업로드 속도를 높일 수 있다.
속도 최적화: 업로드 센터를 사용자 근거리에 지정
업로드 센터를 여러 곳에 두어 업로드 속도를 개선한다.
속도 최적화: 모든 절차를 병령화
느슨하게 결합된 시스템을 만들어서 병렬성을 높이는 것.
이를 위해서는 설계안을 조금 변경해야 한다.
아래 그림은 이전 단계의 결과물을 입력으로 사용하여 만들어진다.
이러한 의존성이 있으면 병렬성을 높이기 어렵다.
- 메세지 큐 도인 전, 인코딩 모듈은 다운로드 모듈의 작업이 끝나기를 기다려야한다.
- 메세지 큐 도입 후, 인코딩 모듈은 다운로드 모듈의 작업이 끝나기를 안 기다려도 된다.
=> 메세지 큐에 보관된 이벤트 각각을 인코딩 모듈은 병렬적으로 처리할 수 있다.
안정성 최적화: 미리 사인된 업로드 URL
올바른 장소에 비디오를 업로드할 수 있도록 하기 위해, 미리 사인된(pre-signed) 업로드 URL을 이용한다.
미리 사인된 URL은 아마존 S3에서 사용하는 용어로 해당 URL이 가리키는 객체에 대한 접근 권한이 이미 주어져있는 상태
안전성 최적화: 비디오 보호
비디오 저작원을 보호하기 위해 세 가지 방법이 있다.
- 디지털 저작권 관리 시스템 도입: 애플의 페어플레이, 구글의 와이드바인, 마이크로소프트의 플레이레디
- AES 암호화: 비디오를 암호화하고 접근 권한을 설정하는 방식, 허락된 사용자만 암호화된 비디오를 시청 간으
- 워터마크: 비디오 위에 소유자 정보를 포함하는 이미지 오버레이를 올리는 것.
비용 최적화
유튜브의 비디오 스트리밍은 롱테일 분포를 따른다.
인기 있는 비디오는 빈번히 재생되고 나머지는 거의 보는 사람이 없다.
- 인기 비디오는 CDN을 통해 재생하고, 다른 비디오는 비디오 서버를 통해 재생
- 인기가 별로 없는 비디오는 인코딩할 필요가 없을 수도 있다.
- 어떤 비디오는 특정 지역에서만 인기가 높다. 그럼 해당 지역으로 옮긴다.
- 인터넷 서비스 제공자와 제휴
오류 처리
- 회복 가능 오류: 특정 비디오 세그먼트를 트랜스코딩하다 실패하는 오류는 회복 가능한 오류에 속한다.
해당 오류는 몇 번 재시도 하면 해결된다. - 회복 불가능 오류: 비디오 포맷이 잘못되었거나 하는 회복 불가능한 오류
해당 비디오에 대한 작업을 중단하고 클라이언트에게 적절한 오류 코드를 반환해야한다.
시스템 컴포넌트 각각에 발생할 수 있는 오류
- 업로드 오류: 몇 번 재시도
- 비디오 분할 오류: 낡은 버전의 클라이언트가 GOP 경계에 따라 비디오를 분할하지 못하는 경우라면 전체 비디오를 서버로 전송하고 서버가 해당 비디오를 분할 처리
- 트랜스코딩 오류: 재시도
- 전처리 오류: DAG 그래프를 재생성
- DAG 스케줄러 오류: 작업을 다시 스케줄링
- 자원 관리자 큐에 장애 발생: 사본(replica)을 이용
- 작업 서버 장애: 다른 서버에서 해당 작업을 재시도
- API 서버 장애: API 서버는 무상태 서버이므로 신규 요청은 다른 API 서버로 우회
- 메타데이터 캐시 서버 장애: 다중화 되어 있으므로 다른 노드에서 데이터 가져오고, 장애가 난 캐시 서버는 새로운 걸로 교체
- 메타데이터 데이터베이스 서버 장애
- 주 서버가 죽었다면 부 서버 가운데 하나를 주 서버로 교체
- 부 서버가 죽었다면 다른 부 서버를 통해 읽기 연산을 처리하고 죽은 서버는 새 것으로 교체
4단계 마무리
추가적으로 논의할 사항
- API 계층의 규모확장성
- 데이터 베이스 계층의 규모 확장성
- 라이브 스트리밍
- 비디오 삭제
등이 있다.