Skip to content

Commit

Permalink
7,8,9,10장 내용 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
LenKIM committed Apr 7, 2024
1 parent 95722d6 commit 9cf4994
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 0 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 분산 시스템을 위한 유일 ID 생성기 설계

1) 문제 이해 및 설계 범위 확장
- ID는 유일해야 한다.
- ID는 숫자로만 구성되어야 한다.
- ID는 64비트로 표현될 수 있는 값이어야 한다.
- ID는 발급 날짜에 따라 정렬 가능해야 한다.
- 초당 10,000개의 ID를 만들 수 있어야 한다.
2) 계략적 설계안 제시 및 동의 구하기
- 다중 마스터 복제
- UUID
- 티켓 서버
- 트위터 스노우플레이크
3) 상세 설계

4) 마무리
165 changes: 165 additions & 0 deletions docs/len/presentation/8장-URL 단축기 설계.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# URL 단축기 설계

고전적인 시스템 설계

이전에 내가 이걸 실패했던 이유는 설계의 본질이 틀렸기 때문에.

도메인 모델링과 시스템 설계는 다른 것인데, 잘못 접근했다.

URL 단축기 설계를 들여다 보자.



#### 1단계. 문제 이해 및 설계 범위 확장

어떻게 URL 단축기가 동작할까?

질문을 해야지ㅣ....

1. 트래픽 규모는 얼마나 될까요?
= 매일 1억개의 단축 URL 을 만들어 낼 수 있어야 합니다.
2. 길이는 어느 정도여야 하나요?
= 짧으면 짧을수록 좋습니다.
3. 포함될 문제에 제한이 있나요?
= 숫자, 영문자만 사용할 수 있습니다.
4. 단축된 URL을 시스템에서 지우거나 갱신할 수 있습니까?
= 시스템을 단순화하기 위해 삭제나 갱신은 할 수 없다고 가정

**기본적 기능은 다음과 같다**

1. URL 단축 - 주어진 긴 URL을 휠씬 짧게 줄인다.
2. URL 리디렉션(redirection) - 축약된 URL로 HTTP 요청이 오면 원래 URL로 안내
3. **높은 가용성과 규모 확장성, 그리고 장애 감내가 요구됨**



**개략적 추정**

- 쓰기 연산: 매일 1억 개의 단축 URL 생성
- 초당 쓰기 연산: 1억/24/3600 = 1160
- 읽기 연산: 읽기 연산과 쓰기 연산 비율은 10:1이라고 하자. 그 경우 읽기 연산은 초당 11,600회 발생(1160 x 10)
- URL 단축 서비스를 10년간 운영한다고 가정하면 1억(100milion) x 365 x 10 = 3650억개의 레코드 보관
- 축약 전 URL의 평균 길이는 100이라고 가정
- 따라서 10년 동안 필요한 저장 용량은 3650억 x 100바이트 = 36.5TB

#### 2단계. 개략적 설계안 제시 및 동의 구하기

API 엔드포인트(endpoint), URL 리디렉션, URL 단축 Flow

##### API Endpoint

클라이언트는 서버가 제공하는 API 엔드포인트

REST 스타일의 엔드포인트

1. **POST /api/v1/data/shorten**

- 인자: {longUrl: longURLString}
- 반환: 단축 URL

2. **GET /api/v1/shortUrl**

- 반환: HTTP 리디렉션 목적지가 될 원래 URL



**URL 리디렉션?**

<img src="https://raw.githubusercontent.com/LenKIM/images/master/2024-03-29/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.54.47.png" alt="스크린샷 2024-03-29 오후 9.54.47" style="zoom:50%;" />



- 단축 URL을 받은 서버는 그 URL을 원래 URL로 바꾸어서 301응답의 Location 헤더에 넣어 반환

- 301 Permanently Moved 과 302 Found 의 차이점

- 301 - 해당 URL에 대한 HTTP 요청의 처리 책임이 영구적으로 Location 헤더에 반환된 URL로 이전되었다는 응답. 영구적으로 이전되었으므로, 브라우저는 이 응답을 캐시(cache). 따라서 추후 같은 단축 URL에 요청을 보낼 필요가 있을 때 브라우저는 캐시된 원래 URL로 요청을 보내게 됨
- 302 - 주어진 URL로의 요청이 '일시적으로' Location 헤더가 지정하는 URl에 의해 처리되어야 한다는 응답. 따라서 클라이언트의 요청은 언제나 단축 URL 서버에 먼저 보내진 후에 원래 URL로 리디렉션되어야 한다.

차이는, 서버 부하를 줄이는 것이 중요하다면 301 Permanent Moved 를 사용하는 것이 좋은데 첫 번째 요청만 단축 URL서버로 전송될 것이기 때문. 하지만 트래픽 분석(analytics) 중요할 때는 302 쓰는쪽이 클릭 발생률이나 위치를 추적하는데 좀더 유리.

- URL 리디렉션을 구현하는 가장 직관적인 방법은 해시 테이블을 사용하는 것.

- <단축 URL, 원래 URL> 의 쌍을 저장해서 구현될 수 있다.

- 원래 URL = hashTable.get(단축 URL)
- 301 또는 302 응답 Location 헤더에 원래 URL을 넣은 후 전송

**URL 단축**

긴 URL -----------------> f(x) [해시] -----------> http://tinyurl.com/[shortUrl]



#### 3단계. 상세 모델

개략적 설계를 진행할 때는 모든 것을 해시 테이블에 놓으면 메모리가 비싸기 때문에, 관계형 데이터베이스에 넣는다.

**해시 함수는 어떤 것을 사용할 것인가?**

hashValue의 길이를 정하기 위해서는 62(0-9, a-z, A-Z)^n >= 3650억인 n의 최솟값을 찾아야 한다. 왜냐하면 요구사항이 3650억이니까.

n = 62^1 = 62

n = 62^2 = 3,844

n = 62^3 = 238,328

n = 62^4 = 12,776,336

...

n = 7 이면 3.5조 개의 URL 을 만들 수 있고, 요구사항을 만족시키기 충분한 값.

해수 함수 구현에 쓰일 기술로 두 가지 방법이 있다

1. 해시후 충돌 해소
- CRC32, MD5, SHA-1 같이 잘 알려진 해시 함수 이용하는 방법
- 길이가 길기 때문에 처음 7개 글자만 이용
- 이 방법의 단점으로, 충돌을 해소할 수 있지만 단축 URL을 생성할 때 한 번 이상 데이터베이스 질의를 해야 하므로 오버헤드가 크다. DB대신 블룸 필터를 사용하면 성능을 높일 수 있다.
2. base62 변환
- 진법 변환(base conversion)은 URl 단축기 구현시 흔히 접근법 중 하나. 이 기법은 수의 표현 방식이 다른 두 시스템이 같은 수를 공유하여야 하는 경우 유용

| 해시 후 충돌 해소 전략 | base-62 전략 |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| 단축 URL의 길이가 고정됨 | 단축 URL의 길이가 가변적. ID 값이 커지면 같이 길어짐 |
| 유일성이 보장되는 ID 생성기가 필요치 않음 | 유일성 보장 ID 생성기가 필요 |
| 충돌이 가능해서 해소 전략이 필요 | ID의 유일성이 보장된 후에야 적용 가능한 전략이라 충돌은 아예 불가능 |
| ID로부터 단축 URL을 계산하는 방식이 아니라서 다음에 쓸 수 있는 URL을 알아내는 것이 불가능 | ID가 1씩 증가하는 값이라고 가정하면 다음에 쓸 수 있는 단축 URL이 무엇인지 쉽게 알아낼 수 있어서 보안상 문제가 될 소지가 있음 |

**URL 단축시 상세 설계**

시스템의 핵심 컴포넌트

1. 입력으로 긴 URL을 받는다.
2. 데이터베이스에 해당 URL이 있는지 검사
3. 데이터베이스에 있다면 해당 URL에 대한 단축 URL을 만든 적이 있는 것이다. 따라서 데이터베이스에서 해당 단축 URL을 가져와서 클라에게 반환
4. 없는 경우에는 해당 URL은 새로 접수된 것으므로 유일한 ID 생성. 이 ID는 데이터베이스의 기본 키로 사용
5. 62진법 변환. ID를 단축 URL로 만듬
6. ID, 단축 URL, 원래 URL로 새 데이터베이스 레코드 만든 후 단축 URL을 클라에게 전달.



이해가 조금 어렵다면 아래의 예제 살펴보자

- 입력된 URL이 http ... 이라고 하자
- 이 URL에 대해 ID 생성기가 반환한 ID 은 20092
- 이 ID를 62진수로 변환하면 zn9edcu 얻는다.
- 그다음 레코드를 만들어 저장한다.



**URL 리디렉션 상세 설계**

<img src="https://raw.githubusercontent.com/LenKIM/images/master/2024-03-29/image-20240329232704180.png" alt="image-20240329232704180" style="zoom:50%;" />

#### 4단계 마무리

설계를 마친 후에도 시간이 좀 남는다면 다음과 같은 것을 면접관과 이야기 할 수 있을 것

- 처리율 제한 장치(rate limiter)
- 엄청난 양의 URL 단축 요청이 밀려들 경우 무력화될 수 있다는 잠재적 보안 결함을 갖고 있다. IP주소를 비롯한 필터링 규칙(filtering rule)들을 이용해 요청을 걸러낼 수 있을 것이다.
- 웹 서버의 규모 확장: 본 설계에 포함된 웹 계층은 무상태(stateless)계층이므로, 웹 서버를 자유로이 증설하거나 삭제
- 데이터베이스의 규모 확장
- 데이터 분석 솔류션

Binary file not shown.

0 comments on commit 9cf4994

Please sign in to comment.