월간-CS, 대규모 시스템 설계면접 2권 스터디 발표 자료입니다. - [Ref]
11.11.월 ~ 11.14. 목 까지 작성한 DIL을 기반으로 준비하였습니다. - [Ref
시작에 앞서
대규모 시스템 설계 면접에서는 4가지 단계*로 인프라를 설계합니다.
보통 요구사항 이해, 개략적인 규모 추정, 추상적 설계, 상세 설계 순으로 진행됩니다.
저는 전체과정을 30분으로 제한하고 면접 과정을 가상으로 설계해보았습니다.
1. 요구사항 이해
본 문서에서는 아키텍처 측면을 포커스하고 있습니다.
따라서 API 명세의 종류는 당연히 논의하였다고 가정하고 작성하겠습니다.
도메인에 대한 간단한 질의 응답
해당 도메인의 코어 로직에 대한 CAP 논의
지연 시간 및 내구성에 대한 논의
1~2 과정을 포함하여 총 5분 안에 완료한다.
1.1. 도메인에 대한 간단한 질의 응답
서비스 “주변 친구”는 주변에 있는 친구 목록과 그 거리를 보여줍니다.
주변의 기준은 5km 으로 하며 모든 이동 정보는 로그 형태로 저장되어야 합니다.
아카이빙의 목적은 머신러닝에서 쓰이기 위함입니다.
1.2. 해당 도메인의 코어 로직에 대한 CAP 논의
1장 발표에서도 말한 것처럼 CAP 관점에서 중요한 것이 무엇인지 고민해야 합니다.
CAP 정리에 따르면 데이터 일관성(Constistency)*과 가용성(Availability)*을 모두 만족하는 시스템은 존재할 수 없습니다. 따라서 일관성과 가용성 중 무엇을 우선으로 하는 서비스인지는 매우 중요한 요소입니다.
43p 결과적 일관성(Eventually Consistnency) 부분에서
우리는 이 서비스는 최종 일관성(Final Consistency)*을 충족하면 됨을 알았습니다.
즉 일부 가용성을 포기한 대신 시스템 가용성(Availability)*을 지켜야 합니다.
1.3. 지연 시간 및 내구성에 대한 논의
우리는 강한 일관성*을 포기함으로써 시스템의 유연한 설계가 가능해졌습니다.
이를 발판으로 낮은 지연시간(500ms 미만)*에 기능이 작동되기를 원합니다.
이를 위해서 스트림, 인메모리 등의 기법을 적극적으로 활용해야 합니다.
2. 개략적인 규모 추정
전체 유저 수 : 10억
실제 사용자 수 : 1억 (10억 * 10%)
동시 접속자 수 : 1000만 (1억 & 10%)
초당 위치 정보 갱신 수 : 1000만/30초 = 33만 4천
사용자 당 평균 친구 수 : 400명(평균)
초당 위치 정보 조회 수 : 1000만/30초*400명(평균) = 1억 3600만
3. 개략적인 설계안 제시 및 동의 구하기
이 단계에서는 주제에서 가장 어려운 기술적인 난제가 무엇인지를 면접관과 함께 확정하고 이를 해결하는 아키텍처에 대해서 다루고자 합니다. 따라서 아래의 3가지 단계로 설계안을 그려 나갑니다.
기술적인 난제 선정 및 근거에 대한 생각 공유
기술적인 난제를 해결하기 위한 핵심 아키텍처 설계
부수적인 문제를 해결하기 위한 보조 아키텍처 설계
3.1. 기술적인 난제 선정 및 근거에 대한 생각 공유
서비스 “주변 친구”의 가장 큰 문제는 대량의 요청이 실시간으로 처리된다는 점입니다.
앞서 데이터 갱신은 약 33만, 조회는 1억 3600만 정도로 예측하였습니다. - [Ref]
갱신 주기는 30초 이므로 조회 반영은 최대 29초 안에 완료되어야 합니다.
따라서 핵심적인 기술 난제는 갱신과 요청 관점에서 발생합니다.
데이터 갱신 자체를 줄이는 방법
데이터 조회 자체를 줄이는 방법
3.2. 난제 - 데이터 갱신 자체를 줄이는 방법
위치기반 서비스는 GPS에 의존하고 따라서 GPS 오차범위*를 제약사항으로 가진다.
또한 서비스의 정책에 따라서 최소 정밀도의 위치가 몇 미터*도 중요 변수입니다.
만약 친구 간의 거리의 최소값을 10m*로 정하고 개인의 정밀도를 5m*라고 한다면,
마지막 위치에서부터 5m 미만의 위치 변경은 크게 신뢰할 수 없을 것입니다.
따라서 움직인 순간에만 그 정보가 갱신되도록 구현할 수 있을 것입니다.
33만 4천 건 중에서 30초 당 5m 이하로 움직이는 유저가 50%라면,
이런 방법으로 초당 위치 정보 갱신 수도 50% 감소시킬 수 있습니다.
AS-IS : 33만 4천 건
TO-BE : 16만 7천 건
즉, 클라이언트 단의 로직으로 요청량을 줄일 수 있습니다.
이런 방법에 문제점이 있을까? 잘 모르겠습니다.
3.3. 난제 - 데이터 조회를 줄이는 방법
초당 33만 4천 건의 갱신은 요청 1건당 평균 400명에게 반영되어야 한다.
따라서 1억 3600만 건의 조회가 1초당 이루어지므로 대량의 조회가 발생한다.
다만 3.2. 데이터 갱신 자체를 줄이는 방법에서
요청량을 50% 줄이더라도 일반적인 스케줄링 방식으로 데이터를 조회한다면
최종적으로 100%의 요청인 1억 3600만 건의 요청이 여전히 발생합니다.
이를 위해서 Redis Publish Subscribe Channel을 활용한다면,
데이터가 갱신된 시점에만 내 친구들(400명)에게 이벤트를 구독시킬 수 있다. - [Ref]
1억 3600만 건 중에서 갱신 절감분인 50%(가설)을 차감한,
6800만 건의 데이터만 실시간으로 조회되도록 할 수 있다.
3.4. 문제 - 로그 데이터 수집의 문제
요청 별로 생기는 로그 데이터를 모두 OLTP에 기록하는 것은 비현실적인 가정입니다.
OLTP에 초당 33만 4천 건의 위치 로그가 기록될 경우에 대량의 디스크 플러시 과정으로 DB에 장애가 생기거나 높은 비용을 지불해야 할 수 있습니다.
따라서 로그 데이터는 확장성이 높은 스토리지와 OLAP DB에서 관리해야 합니다/
그렇다면 근본적으로 1000만 명의 사용가 만드는 용량을 얼마나 될까요?
사용자 1000만 명은 30초당 0.4 GB의 위치로그를 생성합니다.
(실제로는 이보다 클 것이지만 그 외의 메타 데이터는 제외하였습니다.)
사용자 1명 = 40 Byte
사용자 1000만명 = 400,000,000 Byte = 0.4 GB
사용자 1명의 위치 정보 크기 ( 36 ~ 40 byte )
UUID : 128 bit = 16 byte
위도/경도 : float = 8 byte
위도 + 경도 = 16 byte
Unix timestamp = 4 byte/8 btye (32bit/64bit)
사용자 1000만 명의 위치 정보 크기 ( 0.4 GB )
400,000,000 Byte / 1000 Byte/KB = 400,000 KB
400,000 KB / 1000 KB/MB = 400 MB
400 MB / 1000 MB/GB = 0.4 GB
이 금액을 기준으로 시간당, 일별, 월별, 연도별 용량을 계산하면 다음과 같습니다.
시간당 : 0.4 GB/30s * 3600 s/h = 48 GB
일별 : 48 GB/h * 24 h/m = 1,152 GB = 1.152TB
월별 : 1.152 TB/h * 30.5 d/m = 35.136 TB = 35.136 TB
연도별 : 1.152 TB/h * 365.25 d/y = 420.768 TB = 420.768 TB
4. 상세 설계
이 단계에서는 핵심 아키텍처와 보조 아키텍처 각 1건에 대해서 다루고자 합니다.
위치정보 갱신 및 조회 아키텍처
위치로그 수집 및 조회 아키텍처
본 장에서는 총 15분을 배정하고 사용하려고 합니다.
4.1. 위치정보 갱신 및 조회 아키텍처
본 도서에서는 Redis Pub/Sub Channel 할당을 위해서 해시링 개념을 사용합니다.
해시링이란 x0부터 xN까지 선형적인 공간의 끝인 (x0,xN)을 연결한 원을 의미합니다.
이 해시링에는 M개의 채널이 할당될 것이며, 해시 함수의 결과에 따라서 각 채널을 할당받습니다.
이 방식의 치명적인 문제점은 채널의 숫자의 변동에 의해서 발생합니다.
만약 선형 공간을 나누던 채널의 갯수가 M에서 M+1일이 된다면 아래와 같다.
각 채널의 선형 연결 고리의 사이에 새로운 서버가 생겨남으로써 1개의 연결을 끊고 2개의 연결을 새로 맺어야 한다.
서버가 제거되는 경우에도 이와 유사한 문제가 발생한다.
이러한 경우에는 안정해시를 통해서 이 문제를 해결할 수 있고
안정 해시에 대해서는 제한 시간을 벗어나는 범위이기 때문에 추가적으로 다루지 않는 것이 옳다고 생각합니다.
4.2. 위치로그 수집 및 조회 아키텍처
초당 13MB 정도의 로그 수집 요청이 들어오면서
일별 1.152 TB 정도의 로그가 수집되는 구조에서 어떤 설계를 해야할까요?
(30초당 0.4GB)
가장 안정적인 방법은 사이드카 기반의 로그 수집 방식입니다.
이를 클라우드 환경에서 오픈소스를 결합하여 구축하면 다음과 같습니다.
네트워크 전송 단계의 성능 및 비용을 추가 절감하기 위해서는 다음과 같습니다.
여기서 스토리지 최적화를 진행할 수 있습니다.