https://product.kyobobook.co.kr/detail/S000001033116

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

검색어 자동완성 기능은 대부분의 서비스에서 제공하고 있는 기능이다. 하지만 이 시스템의 설계안에 대해 한번도 고민해지 않아서 주제를 보면서 더욱 흥미롭게 느껴졌다.

 

요구사항

- 사용자가 입력한 단어는 자동완성될 검색어의 첫 부분이다.

- 5개의 자동완성 검색어가 표시된다.

- 질의 빈도에 따른 검색어 인기 순위를 기준으로 보여준다.

- 맞춤법 검사나 자동수정은 지원하지 않는다.

- 질의는 영어이다. 하지만 다국어 지원을 생각해도 좋다.

- 대문자나 특수문자는 고려하지 않는다.

- DAU는 1000만명이다.

 

요구사항 분석

- 빠른 응답 속도 : 시스템 응답속도는 100밀리초 이내여야 한다.(페이스북의 검색어 자동완성 시스템 문서 참조)

- 연관성 : 자동완성되어 출력되는 검색어는 사용자가 입력한 단어와 연관되어야 한다.

- 정렬 : 인기도 등의 순위 모델에 의해 정렬되어 있어야 한다.

- 규모 확장성 : 시스템은 많은 트래픽을 감당할 수 있도록 확장 가능해야한다.

- 고가용성 : 시스템의 일부에 장애가 발생하거나, 느려지거나, 네트워크 문제가 생겨도 시스템은 계속 사용가능해야 한다. 

 

규모 추정

- DAU : 1000만명

- 한 사용자는 매일 10건의 검색 수행

- 질의할 때마다 평균적으로 20Byte 데이터 입력

- 1회 검색당 20건의 요청이 백엔드로 전송(글자를 입력할 때마다 클라이언트는 백엔드에 요청을 보냄)

- 초당 24000건의 질의가 발생(10,000,000사용자 * 10질의 * 20자 / 24시간/ 3600초)

 

개략적인 설계안

자동완성 시스템은 두 부분으로 나뉜다.

- 데이터 수집 서비스 : 사용자가 입력한 질의를 실시간으로 수집하는 시스템(실시간은 부적절 하지만 차후 보안하자)

- 질의 서비스 : 주어진 질의에 다섯 개의 인기 검색어를 정렬해 내놓는 서비스

 

데이터 수집 서비스

데이터 수집 서비스는 각각의 검색어가 몇번의 질의를 받았는지 기록해 두는 시스템이다. 만약 사용자가 twitch, twitter, twitter, twillo를 순서대로 검색하면, 다음과 같이 테이블에 데이터가 변경되어간다.

 

1. twitch : 1

 

2. twitch : 1

    twitter : 1

 

3. twitch : 1

    twitter : 2

 

4. twitch : 1

    twitter : 2

    twillo : 1

 

질의 서비스

앞서 기록한 데이터 수집 서비스에서 저장한 데이터에 SQL Query를 사용해 가장 많이 사용된 5개의 검색어를 계산할 수 있다.

SELECT * FROM frequency_table
WHERE query Like `prefile%`
ORDER BY frequency DESC
LIMIT 5;

데이터 양이 적다면 나쁘지 않은 설계안이다. 하지만 데이터가 많아지면 데이터베이스가 병목이 될 수 있다. 이제 이 문제를 해결할 방법을 앞으로 알아본다.

 

상세 설계

앞선 개략적 설계안을 개선하기 위해 트라이 자료구조, 데이터 수집 서비스, 질의 서비스 순으로 살펴보자.

 

트라이 자료구조

트라이 자료구조에 대한 상세한 설명은 이미 잘 알려져 있고, 좋은 자료도 많기 때문에 생략하겠다. 하지만 트라이 자료구조의 한계를 잠깐 언급하고 이어서 한계를 극복하는 방식에 대해 이야기 하겠다.

트라이 자료구조는 탐색을 위해 O(p) + O(c) + O(clogc) 이다. 이때 p는 접두어의 길이, n은 트라이 안에 있는 노드 개수, c는 주어진 노드의 자식 노드 개수이다. 이 알고리즘은 직관적이지만 최악의 경우에는 k개의 결과를 얻으려고 전체 트라이를 다 검색해야 하는 일이 생길 수 있다. 이 문제를 해결하기 위해 접두어 최대 길이 제한, 노드에 인기 검색어 캐시 하는 방식으로 최적화를 진행한다.

 

- 접두어 최대 길이 제한

앞서 접두어의 길이 p는 시간 복잡도에 영향을 끼친다. 여기서 접두어의 길이를 상수, 예컨데 50으로 제한 한다면 O(p)는 O(1)으로 변경된다.

 

- 노드에 인기 검색어 캐시

각 노드에서 인기있는 검색어 5개를 저장해 두면 시간 복잡도를 엄청나게 낮출 수 있다. 물론 저장 공간을 많이 희생하게 된다는 단점이 있지만, 빠른 응답속도가 아주 중요할 때는 희생할 만한 가치가 있다. 

 

앞선 두가지의 최적화를 진행하면 접두어 노드를 찾는 시간 복잡도는 O(1)이 되고, 최고 인기 검색어 5개를 찾는 질의의 시간 복잡도도 O(1)이 된다. 즉, 전체 알고리즘의 복잡도도 O(1)이 된다.

 

데이터 수집 서비스

최초의 설계안은 요청이 들어올 때 마다 실시간을 데이터를 수정했다. 하지만 이 방식은 매일 수천만 건의 질의가 입력되는 요구사항에서는 심각하게 느려질 것이다. 또한 트라이가 만들어지고 나면 인기 검색어는 자주 변경되지 않기 때문에 비효율 적이다. 

이 문제들을 해결하기 위해 개선된 설계안은 다음과 같다. 아래에서 개선된 설계안의 각 컴포넌트에 대한 설명을 이어서 한다. 

- 데이터 분석 서비스 로그

데이터 분석 서비스 로그에는 사용자가 입력한 질의를 저장한다. 수정이나 삭제는 이루어지지 않으며, 로그 데이터에는 인덱스를 걸지 않는다.

Query Time
tree 2023-01-01 22:01:02
try 2023-01-01 22:01:03
test 2023-01-01 22:01:06

- 로그 취합 서버

데이터 분석 서비스에서 적재된 로그는 일정한 주기로 검색 횟수를 취합한다. 이때 트위터와 같이 데이터의 신선도가 중요한 서비스는 자주 취합해 주고, 구글과 같은 서비스는 더 긴 주기를 가져도 좋을 것이다.

 

- 취합된 데이터

time 필드는 해당 주가 시작된 날짜를 나타낸다.

query time frequency
tree 2023-01-01 12000
tree 2023-01-08 15000
tree 2023-01-15 9000
toy 2023-01-01 8500
toy 2023-01-08 6256
toy 2023-01-15 8866

 

- 작업 서버

작업 서버는 주기적으로 비동기적 잡업(job)을 실행하는 서버 집합이다. 트라이 자료구조를 만들고 트라이 데이터베이스에 저장하는 역할을 담당한다.

 

- 트라이 캐시

트라이 캐시는 분산 캐시 시스템으로 트라이 데이터를 메모리에 유지하여 읽기 연산 성능을 높인다.

 

- 트라이 데이터베이스

Document Store와 Key-Value Store를 통해 지속성 저장소를 구현할 수 있는데, 이 책에선 키-값 저장소를 사용한다.

 

질의 서비스

개략적 설계안에서는 DB를 활용하여 인기 검색어 5개를 골라냈다. 개선된 설계안은 기존 설계안의 비효율성을 개선한 설계안이다.

 

트라이 연산

트라이는 자동완성 시스템의 핵심 컴포넌트이다. 이제 트라이 관련 연산들이 어떻게 이루어 지는지 보자.

- 트라이 생성

트라이 생성은 작업 서버가 담당하며, 취합된 데이터를 활용한다.

 

- 트라이 갱신

트라이 갱신은 매주 새로운 트라이를 만든 후에 대체하는 방법과 각각의 노드를 개별적으로 갱신하는 방법이 있다. 작가는 매주 새로운 트라이를 만드는 방법을 사용했는데, 이는 성능이 좋지 않기 때문이다.

 

- 검색어 삭제

몇몇 단어는 혐오성이 짙거나, 폭력적이거나, 성적으로 노골적인 듯 문제가 되는 검색어를 자동완성 결과에서 제거해야 한다. 이를 위해 캐시 앞에 필터 계층을 두고 부적절한 질의어가 반환되지 않도록 하는 것을 추가할 수 있다.

 

저장소 규모 확장

영어만 지원하지 때문에 첫 글자를 기준으로 샤딩할 수 있다. 영어는 26글자니까 추가로 샤딩하기 위해서 두 번째 글자까지 샤딩할 수 있다. 하지만 모든 글자가 해당 글자로 시작되는 단어를 동일하게 가지고 있는 것은 아니다. 이를 위해서 과거 질의 데이터의 패턴을 분석해서 샤잉하는 방법을 사용한다.

https://product.kyobobook.co.kr/detail/S000001033116

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

요구사항

- 1:1채팅, 그룹 채팅 모두 지원

- 웹/앱 모두 지원

- DAU는 5천만명

- 그룹 채팅 최대 인원은 100명

- 사용자의 접속상태를 표시해야함

- 메시지 길이는 100,000자 이하여야 한다.

- 채팅 이력은 영원히 보관해야 한다.

 

채팅 프로토콜

채팅 서비스는 메시지 송신 클라언트로부터 메시지를 받아서 저장하고, 메시지 수신 클라이언트에게 메시지를 전달해야 한다. 이를 위해 어떤 프로토콜을 사용할지 살펴보자.

- 폴링

폴링은 주기적으로 수신 클라이언트가 서버에게 새 메시지가 있는지 물어보는 방식이다 . 이 방식은 서버 자원 불필요하게 낭비된다는 단점이 있다.

 

- 롱 폴링

폴링의 단점을 완화하기 위해서 새 메시지가 반환되거나 타임아웃 될 때까지 연결을 유지하는 방식이다. 이 방식은 수신 클라이언트와 송신 클라이언트가 다른 서버에 접속할 수도 있다는 문제가 있다. 또한 서버 입장에서 클라이언트가 연결을 해제했는지 아닌지 알 방법이 없다. 그리고 무엇보다 여전히 비효율적이다.

 

- 소켓
웹소켓은 서버가 클라이언트에게 비동기 메시지를 보낼 때 가장 널리 사용하는 기술이다. 웹 소켓은 HTTP 기반의 방식들과 달리 클라이언트가 시작한다. 한번 맺어진 연결을 항구적이며 양방향이다. 웹 소켓을 이용하면 메시지를 보낼 때나 받을 때 동일한 프로토콜을 사용할 수 있으므로 설계와 구현이 단순하고 직관적이다. 다만 웹소켓 연결은 항구적으로 유지되어야 하기 때문에 서버 측에서 연결 관리를 효율적으로 해야 한다.

 

개략적인 설계

개략적인 설계는 무상태 시스템, 상태 유지 시스템, 제 3자 서비스 연동 시스템으로 나눌 수 있다.

 

- 무상태 서비스

무상태 서비스는 일반적인 API서버와 동일하게 로그인, 회원가입, 사용자 프로파일 표시 등을 처리한다.

 

- 상태 유지 서비스

채팅 서버는 상태 유지가 필요하다. 이는 클라이언트가 채팅 서버와 독립적인 네트워크 설정을 유지해야 하기 떄문이다.

 

- 제 3자 서비스 연동

제 3자 서비스는 푸시 알림이다. 새 메시지를 받았다면 앱이 꺼져 있어도 알람이 와야 할 것이다.

 

- 규모의 확장성

SPOF를 막기 위해서라도 규모의 확장성을 고려하는 것은 필수적이다. 위의 언급된 요소들을 하나로 묶으면 다음과 같은 개략적인 설계안이 나온다. (키-값 저장소에는 채팅 이력을 보관한다.)

 

- 저장소

사용자 프로파일/설정/친구 목록 처럼 일반적인 데이터는 RDB에 보관하면서 다중화와 샤딩과 같은 기술을 고려한다.

채팅 이력 데이터는 키-값 저장소를 사용한다. 이를 이해하려면 채팅 이력 데이터의 읽기/쓰기 연산 패턴을 이해 해야 한다.

1. 채팅 이력 데이터는 양이 많다.(페북 메신저는 매일 600억개의 메시지를 처리한다)

2. 최근 주고받은 데이터를 주로 본다. 오래된 메시지는 잘 보지 않는다.

3. 검색 기능, 특정 사용자 언급 메시지, 특정 메시지로 점프 등의 기능을 위해 무작위 데이터 접근하는 기능도 지원해야한다.

4. 1대1채팅 앱의 경우 읽기:쓰기 비율은 대략 1:1이다.

 

이런 특징을 모두 지원하기 위해 키-값 저장소를 사용하는데 그 이유는 다음과 같다.

1. 수평적 규모확장이 쉽다.

2. 접근 지연시간이 낮다.

3. RDB는 롱 테일에 해당하는 부분을 잘 처리하지 못한다. 또한 인텍스가 커지면 데이터 무작위 접근 비용이 증가한다.

4. 이미 많은 채팅 시스템이 키-값 저장소를 사용한다.

 

 - 데이터 모델

키-값 저장소를 사용하기로 했으니 이제 메시지 데이터를 어떤 형태로 보관할 것인지 살펴보자. 왼쪽은 1:1 메시지를 저장할 떄 사용하는 테이블이고, 오른쪽은 그룹 메시지를 저장할 때 사용할 테이블이다.

message_id는 다음과같은 조건을 만족해야 한다.

- 고유해야한다.

- ID값은 정렬 가능해야 하며 시간 순서와 일치해야 한다.

이를 위한 전략은 앞서 살펴본 SnowFlake와 같은 방식과 지역적 순서 번호 생성기를 이용하는 것이다. 여기서 지역적 순서 번호 생성기는 ID의 유일성은 같은 그룹 안에서만 보증하면 충분하는 것이다.

 

상세 설계

이제 상세 설계를 살펴보자

 

서비스 탐색(상세 설계)

서비스 탐색 기능의 주된 역할은 클라이언트에게 가장 적합한 채팅 서버를 추천해 주는 것이다. 이때 위치, 서버 용량 등을 기준으로 선택한다. 이를 위해 아파치 주키퍼와 같은 오픈소스를 사용할 수 있다. 서비스 탐색은 다음과 같이 동작한다.

 

메시지 흐름(상세 설계)

1.1:1 채팅 메시지 처리 흐름

2. 여러 단말 사이의 메시지 동기화

채팅은 모바일, 데스크톱, 테블릿 등의 다양한 단말에서 사용할 수 있다. 각 단말을 동기화 하는 방식은 다음과 같은 방식으로 이루어 진다.

채팅 서버에서는 사용자의 모든 단말에 대한 웹 소캣 연결을 유지한다. 그리고 각 단말은 본인이 읽어온 가장 최신 메시지의 ID를 가지고 있다. 이제 각 단말에 접근했을 때 다음과 같은 2가지 조건을 만족하는 메시지는 새 메시지로 간주한다.

- 수신자 ID가 현재 로그인한 사용자 ID와 같다.

- 키-값 저장소에 보관된 메시지로서, 그 ID가 cur_max_message_id보다 크다.

 

- 소규모 그룹 채팅에서의 메시지 흐름

현재 요구사항은 그룹채팅이 500명까지 가능하므로, 소규모라고 볼 수 있다. 이를 위해서는 메시지 큐를 사용자 단말마다 하나씩 생성해서 두고, 송신 측에서 보내야 하는 사용자에게 넣어주면 된다.

이 방식은 소규모 그룹 채팅에서 적합한데 그 이유는 새 메시지를 확인하기 위해 자기 큐만 보면 되니까 동기화가 쉽고, 그룹이 크지 않다면 메시지를 수신자별로 복사해서 큐에 넣는 작업의 비용이 크지 않기 때문에 좋다.

 

접속상태 표시(상세 설계)

클라이언트와 실시간 서비스 사이에 웹소켓 연결이 맺어지고 나면 접속상태 서버는 A의 상태와 last_active_at 타임스탬프 값을 키-값 저장소에 보관한다.이로서 해당 사용자는 접속 중으로 표시 될 것이다.

로그 아웃은 단순히 키-값 저장소에 저장소에 보관된 사용자 상태가 online에서 offline으로 변경되면 된다.

 

- 접속 장애

네트워크 환경은 언제가 가용하지 않는다. 예컨데 터널만 들어가도 그렇다. 그래서 x초 이상 통신이 되지 않는 경우에만 접속상태를 offline으로 변경해야 한다. 이를 위해서 저자는 박동(heartbeat)검사를 제안한다. 즉, 온라인 상태의 클라이언트로 하여금 주기적으로 박동 이벤트를 서버로 보내고, 마지막 이벤트를 받은 지 x초가 지나도 다음 박동 이벤트가 오지 않으면 오프라인으로 바꾸는 것이다.

 

- 상태 정보의 전송

발행-구독 모델을 사용해서 사용자의 상태 변화를 알릴 수 있다. 이는 친구관계당 하나씩 채널을 두는 것으로 하면 된다. 이 방법은 그룹의 크기가 작을 때 효과적이다. 하지만 그룹 크기가 커지면 이런 식으로 접속 상태 변화를 알려서는 비용이나 시간이 많이 들게 되므로 좋지 않다.

 

근데 왜 친구관계당 하나씩 두는지는 잘 이해되지 않는다. 사용자당 하나의 채널을 만들어두고, 구독자를 여러명 두면 되는 것 아닌가? 메시지가 소비되는 것이 문제라면 메시지에 읽어야 하는 사용자 수를 기록해 두고 한명의 사용자가 읽을 때마다 1씩 감소시켜서 0이 되면 메시지를 최종적으로 삭제하도록 할 수는 없는것인가? 혹시 동시성 문제가 걱정되는 것인가?

 

https://product.kyobobook.co.kr/detail/S000001033116

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

뉴스피드 설계는 개인적으로 이해하기 어려운 부분이 있었다. 마이크로 서비스를 시작으로 시스템을 설계하기 때문이다. 하지만 천처히 따라가 보자.

 

요구사항

- 모바일과 웹 둘다 자원하는 시스템이다

- 주요기능 : 새로운 스토리를 올릴 수 있어야 하고, 친구가 올리는 스토리를 볼 수 있어야 한다.

- 뉴스피드는 시간 흐름 역순으로 표시한다.

- 한명의 사용자는 최대 5000명의 친구를 가질 수 있다.

- 매일 천만 명이 방문한다.

- 스토리에 미디어 파일이 포함될 수 있다.

 

개략적 설계안 제시 및 동의 구하기

설계는 피드 발행(feed publishing)과 뉴스 피드 생성(news feed building)의 두 부분으로 나뉘어 진다.

- 피드 발행: 사용자가 스토리를 포스팅하면 해당 데이터를 캐시와 DB에 저장하며, 새 포스팅은 친구의 뉴스 피드에도 전송된다.

- 뉴스 피드 생성: 뉴스 피드는 모든 친구의 포스팅을 시간 흐름에 따라 역순으로 만든다.

 

피드 발행(개략적 설계)

 

뉴스 피드 생성(개략적 설계)

 

피드 발행 흐름 상세 설계

이 시스템은 사용자가 포스팅을 하면 포스트를 DB에 저장하는 피드 발행 시스템과 사용자가 피드를 확인하면 포스트들의 집합을 보여주는 피드 시스템으로 이루어져 있다. 여기서 가장 부하가 많고, 고민스러운 부분은 뉴스 피드를 조회했을 때 수많은 포스트 중에 사용자에게 보여줘야하는 피드가 무엇인지 선택하는 것이다. 심지어 최대한 빠르게 말이다. 이를 위해서 책에선 포스팅 시스템에 전송 서비스를 넣어 둔 것이다. 이를 통해서 사용자에 따라 피드를 빠르게 구성할 수 있다. 여기서 설계자는 포스팅 전송(팬아웃) 서비스를 구성하기 위해 2가지 전략을 선택할 수 있다.

 

- 쓰기 시점에 팬아웃 하는 모델(푸시 모델)

포스팅을 기록하는 시점에 뉴스 피드를 갱신. 즉, 포스팅이 완료되면 바로 해당 사용자의 캐시에 기록

장점

1. 뉴스 피드가 실시간으로 갱신되며 친구 목록에 있는 사용자에게 즉시 전송

2. 새 포스팅이 기록되는 순간 뉴스 피드가 갱신되므로, 뉴스 피드를 읽는 속도가 빠름

단점

1. 친구가 많은 사용자는 전송에 시간이 오래걸린다. 이는 핫키(hotkey) 라고 부르는 문제이다.

2. 서비스를 자주 이용하지 않는 사용자의 피드까지 갱신하는 비효율이 존재

 

- 읽기 시점에 팬아웃 하는 모델(풀 모델)

피드를 읽어야하는 시점에 뉴스 피드를 갱신(on-demand model)

장점

1. 비활성화/자주 사용하지 않는 유저를 위한 컴퓨터 자원을 소모하지 않는다.

2. 핫키 문제가 발생하지 않는다.

단점

1. 뉴스피드를 읽는데 오래 걸릴 수 있다.

 

 

저자는 2가지 방법의 장점을 취하고 단점을 버리는 전략을 제안한다. 대부분에 사용자에 대해서는 푸시 모델을 사용하고, 핫키 문제가 발생할 수 있는 친구나 팔로어가 맣은 사용자는 풀 모델을 사용하는 것이다. 아울러 안정 해시를 통해 요청과 데이터를 보다 고르게 분산하여 핫키 문제를 최소화 한다.

 

피드 읽기 흐름 상세 설계

미디어 파일은 CDN에 저장해서 전송 속도를 높혔다.

https://product.kyobobook.co.kr/detail/S000001033116

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

이 챕터를 읽으면서 호환성과 확장성이 좋은 프로그램을 오픈소스로 만들어보고 싶다는 생각이 들었다. 알람시스템은 언제나 필요하기 때문에 완성도 있는 프로그램을 만들어둔다면 두고두고 잘 쓰지 않을까?

 

 요구사항

- 푸시알림, SMS메시지, 이메일을 지원해야한다.

- 연성 실시간(soft real-time)이어야 한다.

- 푸시알림은 iOS, 안드로이드, 랩톱/데스크톱을 지원해야 한다.

- 알림은 클라이언트 애플리케이션 프로그램이 만들수도, 서버에서 스케줄링 할 수도 있다.

- 사용자가 알람 수신을 거부할 수 있다.

- 하루에 천만 건의 모바일 푸시 알림, 백만 건의 SMS 메시지, 5백만 건의 이메일을 보낼 수 있어야 한다.

 

아래에서는 다음과 같은 내용을 다룬다.

- 알림 유형별 지원 방안

- 연락처 정보 수집 절차

- 알림 전송 및 수신 절차

 

알림 유형별 지원 방안

iOS는 APNS라는 애플이 제공하는 푸시 알림을 iOS장치로 보내는 열할을 담당하는 원격 서비스가 필요하다. 

안드로이드는 APNS 대신 FCM(Firebase Cloud Messaging)을 사용한다.

SMS는 다양한 제3 사업자의 서비스를 사용한다.

이메일 역시 다양한 제3 서비스를 사용한다. 물론 직접 메일 서버를 구축해도 좋지만, 전송 성공률도 높고 데이터 분석도 제공하는 제 3자 서비스가 선호된다.

 

연락처 수집 절차

사용자가 직접 입력해줘야 한다.

 

알림 전송 및 수신 절차

알림 시스템에게 요청을 보내면 알림시스템이 각각의 알림 유형별로 알림보내기 위한 초안이다. 하지만 알림 시스템이 하나의 서버로 이루어져 있어서 몇가지 문제를 발생시킨다. 알림 시스템은 SPOF가 될 것이며, 규모의 확장성(DB나 캐시 등 컴포넌트의 규모를 개별적으로 늘릴 수 없다)이 부족하다. 또한 성능 병목이 될 것이다.

 

 

개략적 설계안(개선된 버전)

DB와 캐시를 분리하고, 메시지 큐를 통해 컴포넌트들 사이의 강한 결합을 끊었다.

 

상세 설계

앞서 살펴본 개략적인 설계에서 다음과 같은 세부 설계를 살펴보쟈ㅏ

- 안정성

- 추가 컴포넌트 및 고려사항

- 개선된 설계안

 

안정성

- 데이터 손실 방지

각 작업서버에서 알림 로그 데이터 베이스를 둬서 어떤 상황에서도 알림이 소실되지 않게 만들 수 있다.

 

- 알림 중복 전송 방지

중복을 완벽하게 막는 것은 불가능하다. 분산 시스템의 특성상 가끔 같은 알림이 중복 전송되기도 할 것이다. 하지만 그 빈도를 줄이기 위해 중복 탐지 알고리즘을 적용할 수 있을 것이다. 그 대표적인 방법으로 이벤트 ID를 검사해서 이전에 본 적이 있는 이벤트인지 살필 수 있다.

 

 추가로 필요한 컴포넌트 및 고려사항

- 알림 템플릿

대형 알림 시스템은 하루에도 수백만 건 이상의 알림을 처리한다. 하지만 대부분 형식이 같으므로 템플릿을 만들어두면 편하게 알림을 보낼 수 있고, 알림들의 형식을 일관성 있게 유지하며, 오류를 줄이고 시간을 아낄 수 있다.

 

- 알림 설정

사용자가 알림을 받고자 하는 채널과 알림 전공 여부를 설정해 줄 수 있다. 이 정보는 알림 설정 테이블에 보관한다.

 

- 전송률 제한

사용자가 너무 많은 알림을 받지않도록 하는 한가지 방법은 사용자가 받을 수 있는 알림의 빈도를 제한하는 것이다. 사용자는 너무 알림이 많으면 알림을 꺼버리기 마련이다.

 

- 재시도 방법

실패한 알림을 재시도 전용 큐에 넣고 재시도 하며, 같은 문제가 반복적으로 발생하면 개발자에게 통지한다.

 

- 푸시 알림과 보안

iOS와 안드로이드는 appKey와 appSecret을 사용하며 보안을 유지한다. 따라서 인증된(또는 승인된) 클라이언트만해당 API를 사용해서 알림을 보낼 수 있다.

 

- 큐 모니터링

큐에 쌓인 알림의 갯수를 모니터링 해서 서버 증설을 계획할 수 있다.

 

-이벤트 추적

데이터 분석 서비스는 보통 이벤트 추적 기능도 제공한다. 따라서 알림 시스템을 만들면 데이터 분석 서비스와 통합해서 알림 확인율, 클릭율, 실제 앱 사용으로 이어지는 비율 등을 확인해야 한다.

 

수정된 설계안

 

  

https://product.kyobobook.co.kr/detail/S000001033116

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

이번 장에서는 웹 크롤러를 설계해본다. 웹 크롤러는 다음과 같은 목표로 사용되곤 한다.

- 검색 엔진 인덱싱

- 웹 아카이빙

- 웹 마이닝

- 웹 모니터링

 

요구사항

- 검색 엔진 인덱싱 용으로 사용

- 1달에 10억 개의 웹 페이지 수집

- 수집한 웹 페이지는 5년간 저장

- 중복 컨텐츠 무시

- 규모의 확장성, 안정성, 예절, 확장성을 확보한다.

 

개략적 규모 추정

- QPS = 10억 * 30일 * 24시간 * 3600초 = 400페이지/초

- Peak QPS = 2* QPS = 800

- 1달간 필요한 저장공간 = 10억 페이지 * 500k(웹 페이지의 평균 크기) = 500TB/월

- 5년간 데이터를 보관한다는 가정 하에 최종적으로 필요한 저장 공간 = 500TB * 12Month * 5년 = 30PB

 

기본적인 구조

우선 기본적인 설계를 살펴본다. 이미 직관적으로 이해가 되는 그림이지만, 각 파트에의 세부적인 부분에 대해서만 조금 이야기해보자.

-미수집 URL 저장소

아직 다운로드 하지 않은 URL을 저장 관리하는 컴포넌트다. FIFO Queue로 구현된다.

 

-콘텐츠 파서

웹 페이지를 다운로드하고 파싱과 검증을 통해 필요없는(또는 이상한) 페이지를 제외한다.

 

-중복 콘텐츠인가?

중복 컨텐츠는 해시 값을 비교하는 것을 통해서 중복을 제거한다.

 

-URL 추출기

HTML페이지를 파싱하여 링크들을 모두 골라낸다.

 

-URL 필터

접근 제외 목록, 오류 발생URL, 특정 콘텐츠 타입이나 파일확장자를 갖는 URL 등을 걸러준다.

 

-이미 방문한 URL?

부하를 줄이고 무한 루프를 방지하기 위해 이미 방문한 URL을 제외한다. 이는 블룸필터나 해시 테이블이 널리 사용된다.

 

상세 설계

DFS vs BFS

DFS를 사용해서 URL을 수집하면 어디까지 깊게 들어갈지 몰라서 선호하지 않는다. 따라서 크롤러는 주로 BFS를 사용하는데, 이도 2가지 문제가 있다. 

첫째로 하이퍼링크로 찾는 URL들은 기존 서버에게로 가는 요청일 확률이 아주 높아서, BFS의 FIFO Queue에 들어가는 URL들이 모두 기존서버일 확률이 높다. 이 수집하려는 사이트에 부하를 줄 수 있어서, 예의 없는 크롤러로 간주된다.

둘째로 BFS 알고리즘은 URL간에 우선순위가 없다. 하지만 페이지 중에서도 중요도를 판단해서 우선순위를 구별하는 것이 좋다.

 

미수집 URL 저장소

예의 있게  URL을 수집하기 위해 같은 호스트에 속하는 모든 URL은 같은 큐에 넣어두자. 그리고 각 큐를 순회하면서 크롤링을 하는 작업 스레드에게 URL 다운로드 작업을 요청한다. 이때 같은 호스트에 속하는 URL끼리는 시간을 두고 수집하기도 한다.

URL간의 우선순위를 두기 위해서 트래픽 양, 갱신 빈도, 페이지 랭크 등의 척도를 사용한다. 우선순위에 의해서 분리된 URL은 각각의 우선순위마다 정의되어있는 큐에 넣는다. 그 뒤로 각 큐에서부터 URL을 꺼내서 앞서 설면한 호스트별 큐에 넣게 된다. 

한번 수집된 페이지가 변경되는 경우도 있다. 이런 경우에는 우선순위에 따라 자주 재수집하거나, 웹 페이지의 변경 이력을 활용할 수 있을 것이다.

 

HTML 다운로더

HTML다운로더에 사용한 수 있는 성능 최적화 방법은 분산 크롤링, 도메인 이름 변환 결과 캐시, 지역성(크롤링 서버를 분산해서 물리적으로 가까운 서버에서 HTML을 다운받는 것), 짧은 타임아웃이 있다. 

 

안정성 확보 전략

안정 해시를 통한 분산 크롤러 서버를 관리하는 것과 크롤링 상태 및 수집 데이터를 저장해서 쉽게 해결하는 전략, 그리고 예외 처리와 데이터검증을 통해 안정성을 확보할 수 있다. 

 

확장성 확보 전략

앞서 보여준 설계에서 URL 추출기를 새로운 모듈로 갈아끼울 수 있도록 설계해서 새로운 형태의 콘텐츠를 지원하는 모듈을 확장할 수있다. 

 

문제 있는 콘텐츠 감지 및 회피 전략

1. 중복콘텐츠

해시나 체크섬을 통해 중복 콘텐츠를 탐지하자.

 

2. 거미 덫

예건케 다음과 같이 무한히 깊은 디렉터리 구조를 포함할 수 있다.

spidertrapexample.com/foo/bar/foo/bar/foo/bar/foo ...

이런 종류는 URL의 최대 길이를 제한하면 된다. 하지만 모든 종류의 덫을 피할 수 있는 해결책은 없다. 이런 덫이 설치된 사이트는 수작업으로 찾은 후 덫이 있는 사이트를 필터로 제안하는 방식이 주로 사용된다.

 

3. 데이터 노이즈

광고나, 스크립트 코드, 스팸 등의 가치없는 데이터는 최대한 제외해야한다.

https://product.kyobobook.co.kr/detail/S000001033116 

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

이번 장에서는 URL 단축 서비스를 설계해 볼 것이다. 그 전에 URL 단축 서비스가 왜 필요한지 먼저 이야기 해보자. 사실 필자는 URL 단축 서비스를 사용해본 적이 없다. 조금 긴 URL을 전송하거나 사용한다고 해서 큰 문제가 발생하지 않기 때문이다. 하지만 아마 twitter와 같이 제한된 글자 수를 보낼 수 있는 서비스를 사용하는 사람들은 URL을 짧게해야 한다는 필요성이 있을 것이다. 최근 자주 보고 있는 유명한 서비스로 bit.ly와 tiney url과 같은 서비스가 있다.

 

요구사항

- URL 단축: 주어진 긴 URL을 훨씬 짧게 줄인다.

- URL 리디렉션(redirection): 축약된 URL로 HTTP 요청이 오면 원래 URL로 안내

- 높은 가용성과 규모 확장성, 그리고 장애 감내가 요구됨

 

개략적인 추정

- 쓰기 연산: 매일 1억 개의 단축 URL 생성

- 초당 쓰기 연상: 1억/24/3600=1160

- 읽기 연산: 읽기 연산과 쓰기연산의 비율을 10:1로 한다. 따라서 초당 읽기 연산은 11600이다.

- URL단축 서비스를 10년간 운영한다고 가정하면 1억*365*10=3650억개의 레코드를 보관해야 한다.

- 축약 전 URL의 평균 길이는 100B라고 가정하자. 따라서 10년 동안 필요한 저장 용량은 3650억 * 100Byte = 36.5TB이다.

 

데이터 모델

단축 URL 서비스를 위해서는 데이터를 어떤 형태로 저장해 둬야할까? 간단하게 DB에 id, shortURL, longURL으로 저장하면 된다. (실제 테이블은 이것보다 더 많은 칼럼을 가질 수 있지만, 간추린 것이다) 이게 logURL으로 shortURL을 만드는 방법을 알아보자.

 

해시함수

앞선 요구사항에서 3650억개의 레코드를 저장해야 했기 때문에, Hash Value의 길이는 7으로 정하자.(hashValue는 [0-9, a-z, A-Z]총 62개의 문자로 구성되며, 62^7 = 약 35조로 충분하다) 해시 함수 구현에 쓰일 기술로는 해시 후 충돌 해소 방법과 base-62변환을 살펴보자.

 

해시 후 충돌 해소

잘 알려진 해시 함수는 CRC32, MD5, SHA-1 등이 있다. 이때 7글자를 넘는 해시 결과는 뒤를 잘라서 사용하자. 이렇게 되면 충돌확률이 증가하는데, 충돌이 발생하면 기존 hashFunction에 넣어줬던 longURL의 맨 뒤에 정해진 문자열을 더해서 다시 hashFunction에 넣어주는 식으로 해결한다.

이 방법은 충돌을 해결하지만, URL을 생성할때 DB 조회를 여러번 해야 하므로 오버헤드가 크다. 이때 어떤 집합에 특정 원소가 있는지 검사할 수 있는 확률론에 기초한 공간 효율이 좋은 기술인 블룸 필터를 사용할 수 있다.

블룸필터는 개념도 간단하고 재미있기 때문에 꼭 찾아보길 추천한다.

 

base-62 변환

base-62방식은 특정 진법으로 되어있는 숫자를 62진법으로 변환하는 것이다. 이때 62진법인 이유는 앞서 확인했던 것 처럼 hashValue가 62개의 문자로 구성되어 있기 때문이다. 이제 ID값을 shortURL 생성 요청이 들어올 때마다 만들어서 생성된 ID를 62진법으로 변환한 결과를 URL으로 사용하게 된다.(ID를 생성하는 방법은 앞선 7장에서 열심히 살펴봤다)

 

 

https://product.kyobobook.co.kr/detail/S000001033116

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

이번 장에서는 분산환경에서 사용될 유일 ID 생성기를 설계한다. auto_increment 속성이 설정된 관계형 데이터베이스의 기본 키를 사용하는 것은 DB서버 한대로 그 요구를 감당할 수 없을 뿐더러, 여러 DB서버를 쓰는 경우에는 지연 시간을 낮추기가 무척 힘들 것이기 때문에 불가능하다. 이제 아래에서 자세한 설계를 살펴본다.

 

 

요구사항

- ID는 유일해야 한다.

- ID는 숫자로만 구성되어야 한다.

- ID는 64비트로 표현될 수 있는 값이어야 한다.

- ID는 발급 날짜에 따라 정렬 가능해야 한다.

- 초당 10,000개의 ID를 만들 수 있어야 한다.

 

후보

1. 다중 마스터 복제(multi-master replication)

다중 마스터 복제는 n개의 DB서버에서 1씩 증가하는 값을 생성하는 것이 아니라, n씩 증가하는 값을 생성하는 것이다. 하지만 이 방식은 여러 데이터 센터에 걸쳐 규모를 늘리기 어려우며, 서버를 추가/삭제할 때도 잘 동작하도록 하기 어렵다. 그리고 ID의 유일성은 보장되지만, 시간이 흐름에 따라 커지도록 할 수 없다.

 

2. UUID

UUID는 랜덤한 값을 사용하는 128비트짜리 수다. 충돌확률이 0에 가깝게 작다.(물론 0은 아니다) UUID는 각 서버에서 독립적으로 ID를 발급하는 방식이기 때문에 동기화이슈도 없고, 단순하다. 또한 규모에 확장 역시 간편하다. 하지만 128비트로 길이가 길고, 시간순으로 정렬할 수 없으며, ID에 숫자가 아닌 값이 포함된다는 단점이 있다.

 

3. 티켓서버

ID를 생성하는 서버를 하나 두고 필요할 때마다 발급 받는 것이다.(아이디를 생성하는 방식은 auto_increment) 이는 유일성이 보장되는 오직 숫자로만 구성된 ID를 쉽게 만들 수 있다. 구현이 쉽고, 중소 규모 애플리케이션에 적합하다. 하지만 티켓서버가 SPOF가 된다는 치명적인 단점이 있다.

 

4. 트위터 스노플레이크 접근법(땅땅땅 결정)

트위터 스노플레이스 ID 생성 기법은 다음과 같다.

사인 비트(1비트) + 타임스탬프(41비트) + 데이터센터 ID(5비트) + 서버 ID(5비트) + 일련번호(12비트)

이 방법은 앞선 모든 요구사항을 만족시킬 수 있다!

https://product.kyobobook.co.kr/detail/S000001033116

 

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | 알렉스 쉬 - 교보문고

가상 면접 사례로 배우는 대규모 시스템 설계 기초 | “페이스북의 뉴스 피드나 메신저,유튜브, 구글 드라이브 같은 대규모 시스템은 어떻게 설계할까?” IT 경력자라도 느닷없이 대규모 시스템

product.kyobobook.co.kr

1장 사용자 수에 따른 규모 확장성 : https://inhyeok-blog.tistory.com/40
2장 개략적인규모추정 : https://inhyeok-blog.tistory.com/41
3장 시스템 설계 면접 공략법 : https://inhyeok-blog.tistory.com/42
4장 처리율제한장치의설계 : https://inhyeok-blog.tistory.com/43
5장 안정해시설계 : https://inhyeok-blog.tistory.com/44
6장 키-값저장소설계 : https://inhyeok-blog.tistory.com/45
7장 분산시스템을위한유일 ID 생성기설계 : https://inhyeok-blog.tistory.com/46
8장 URL 단축기설계 : https://inhyeok-blog.tistory.com/47
9장 웹크롤러설계 : https://inhyeok-blog.tistory.com/48
10장알림시스템설계 : https://inhyeok-blog.tistory.com/49
11장뉴스피드시스템설계 : https://inhyeok-blog.tistory.com/50
12장채팅시스템설계 : https://inhyeok-blog.tistory.com/51
13장검색어자동완성시스템 : https://inhyeok-blog.tistory.com/52
14장유튜브설계 : https://inhyeok-blog.tistory.com/53
15장구글드라이브설계 : https://inhyeok-blog.tistory.com/54

 

이번장도 필자가 재밌게 읽었던 부분 중에 한 파트이다. 특히 5장과 연계되어서 설명되는 다양한 해결책들을 보고있으면 이마를 탁 치게 된다.

 

키-값 저장소에서는 키를 통해서만 값에 접근할 수 있다. 이때 키는 일반 텍스트일 수도 있고 해시 값일 수도 있다. 성능상의 이류로, 키는 짧을수록 좋다.

 

요구사항

- 키-값 쌍의 크기는 10KB 이하이다.

- 큰 데이터를 저장할 수 있어야 한다.

- 높은 가용성을 제공해야 한다. 따라서 트래픽 양에 따라 자동적으로 서버 증설/삭제가 이루어져야 한다.

- 데이터 일관성 수준은 조정이 가능해야 한다.

- 응답 지연시간(latency)이 짧아야 한다.

 

단일 서버 키-값 저장소

이 방식은 아주 쉽다. 가장 직관적인 방식은 메모리에 해시 테이블로 키-값 쌍을 저장하는 것이다. 물론 이 방식은 빠르지만, 저장 공간이 부족할 수 있다. 이를 해결하기 위해서 데이터 압축과 자주 사용되지 않는 데이터는 디스크에 저장하는 방법이 있다. 하지만, 이렇게 개선한다고 해도 앞선 장에서 계속 그랬듯, 단일 서버로는 부족하다. 이제 분산 키-값 저장소를 설계하기 위한 기본 지식으로 CAP 정리를 확인해보자.

 

분산 키-값 저장소

분산시스템을 설계할 때는 CAP 정리를 이해해야한다.

CAP 정리는 일관성(Consistency), 가용성(Availability), 파티션 감내(Partition Tolerance)라는 세가지 요구사항을 동시에 만족하는 분산 시스템을 설계하는 것은 불가능 하다는 것이다. 따라서 목적에 따라 CA시스템, CP시스템, AP시스템 중에 하나를 선택해서 분산 시스템을 설계해야 한다.

 

일관성, 가용성, 파티션 감내의 의미가 어려워서 자세히 적어둔다.

- 일관성: 분산 시스템에 접속하는 모든 클라이언트는 어떤 노드에 접속했느냐에 관계없이 항상 같은 데이터를 보게 된다.

- 가용성: 분산 시스템에 접속하는 클라이언트는 일부 노드에 장애가 발생하더라도 항상 응답을 받을 수 있어야 한다.

- 파티션 감내: 파티션은 두 노드 사이에 통신 장애가 발생하였음을 의미한다. 파티션 감내는 네트워크에 파티션이 생기더라도 시스템은 계속 동작해야 한다는 것을 뜻한다.

 

CA시스템은 파티션 감내가 절대 발생하지 않을 것이라는 아주아주 이상적인 상태를 의미한다.(실세계에선 네트워크 장애를 피할 수 없기 때문에 불가능 하다) 따라서 우린 파티션 문제가 발생하면 우린 일관성과 가용성 사이에서 옵션을 선택해야 한다. 일관성을 지키기 위해서는 CP 시스템을 선택하면 파티션 문제가 발생했을 때 모든 노드에서 쓰기 연산을 중지해야 할 것이다. 따라서 이 방식은 가용성이 깨지게 된다. 반면 AP 시스템은 파티션 문제로 낡은 데이터를 반환하는 한이 있더 계속해서 읽기 연산과 쓰기 연산을 허용한다. 그리고 파티션 문제가 해결 됐을 때 변경된 데이터의 정합성을 맞추는 것이다.

 

이제 설계하려는 시스템의 목적에 따라서 CP 또는 AP 시스템을 설계하면 된다. 

 

시스템 컴포넌트

이제 분산 키-값 저장소를 설계하기 위해 필요한 핵심 컴포넌트들 및 기술들에 대해서 살펴 볼 것이다.

 

1. 데이터 파티션

데이터를 여러 서버에 고르게 분산하기 위해서 5장에서 살펴본 안정 해시를 사용하다. 안정 해시를 사용하므로서 규모의 확장 자동화(시스템 부하에 따라 서버가 자동으로 추가되거나 삭제되는 것)와 다양성(가상 노드를 통해 고성능 서버는 더 많은 가상 노드를 가지게 해서 각 서버에 맞게 데이터의 양을 조절할 수 있다)

 

2. 데이터 다중화

높은 가용성과 안정성을 확보하기 위해서 데이터를 여러 서버에 비동기적으로 다중화 할 필요가 있다. 이는 안정 해시에서 현재 노드 다음 순서에 있는 노드에 데이터를 복제하는 방식으로 달성할 수 있다.

 

3. 데이터 일관성

여러 노드에 다중화된 데이터는 적절히 동기화 되어야 한다. 이를 위해 정족수 합의(Quorum Consensus) 프로토콜을 사용할 수 있다. 정족수 합의 프로토콜의 각 설정값을 조정하는 것으로 응답 지연과 데이터 일관성 사이의 타협점을 찾을 수 있다.

 

4. 일관성 모델

일관성 모델은 키-값 저장소를 설계할 때 고려해야할 또 하나의 중요한 요소다. 일관성 모델은 3가지의 종류가 있는데, 이 개념은 자주 사용되는 개념으로, 이 글에서 간단히 언급하고 넘어가겠다.

- 강한 일관성 : 모든 읽기 연산은 가장 최근에 갱신된 결과를 반환한다.

- 약한 일관성 : 읽기 연산은 가장 최근에 갱신된 결과를 반환하지 못할 수 있다.

- 최종 일관성 : 약한 일관성의 한 형태로, 갱신 결과가 결국에는 모든 사본에 반영되는 모델이다.

강한 일관성을 달성하기 위해서는 모든 사본에 현재 쓰기 연산이 동기화 될 때 까지 해당 데이터에 대한 읽기/쓰기를 금지하는 것이다. 이는 고가용성 시스템에는 적합하지 않다. 따라서 최종 일관성을 자주 사용한다.

 

최종 일관성 모델을 사용하는 경우 비 일관성 해소 방법으로 버저닝과 벡터 시계라는 기술이 있다. 

 

5. 장애 처리

장애 감지

어떤 서버가 죽었다는 사실을 알기 위해서는 모든 노드 사이에 멀티 캐스팅 채널을 구축해서 감지할 수 있다. 하지만 이 방법은 서버가 많으면 분명 비효율적이다. 따라서 가십 프로토콜(hossip protocol), 분산형 장애 감지(decentralized failure detection) 솔루션을 사용하는 것이 효과적이다.

 

일시적 장애 처리

네트워크나 서버 문제로 장애 상태인 서버로 가는 요청은 다른 서버가 잠시 맡아서 처리하고, 해당 서버가 복구 되었을 때 일관 반영하여 데이터 일관성을 보존한다. 이러한 방식을 임시 위탁 기법이라고 부른다.\

 

영구 장애 처리

영구적인 노드의 장애 상태를 처리하기 위해서는 반-엔트로피(anti-entropy)프로토콜을 구현하여 사본들을 동기화 할 것이다. 사본 간의 일관성이 망가진 상태를 탐지하고 전송 데이터의 양을 줄이기 위해서는 머클(Merkle)트리를 활용할 것이다.

 

데이터 센터 장애 처리

데이터 센터 장애에 대응할 수 있는 시스템을 만들기 위해 데이터 센터를 다중화해야한다

+ Recent posts