가상 면접 사례로 배우는 대규모 시스템 설계 기초 (System Design Interview) - 저 : 알렉스 쉬, 역 : 이병준 을 읽고 정리한 글입니다.
1장에서는 사용자 수에 따른 서비스 규모의 확장 흐름에 대해서 이야기합니다.
- 단일서버부터 시작하여, 디비 분리, 서버 분리, 물리적인 데이터센터의 분리 등
- 서비스 규모가 어떤식으로 확장되는지 큰 흐름을 파악할 수 있는 장이였습니다.
➡️ 사용자 수에 따른 적절한 시스템을 설계하기!
[목차]
- 단일서버 구성
- 데이터베이스의 분리
- 수직적 규모확장 vs 수평적 규모확장
- 캐시
- CDN
- 무상태 웹 계층 (Stateless)
- 데이터 센터
- 메시지 큐
- 데이터베이스의 규모 확장 (샤딩과 파티셔닝)
1. 단일 서버
- 복잡한 시스템을 설계하기전에 모든 컴포넌트가 단 한대에서 실행되는 단일서버를 설계해 보자
- 웹 앱, 데이터베이스, 캐시 등이 전부 한 대에서 실행하는 시스템을 보면서 클라이언트가 요청을 보낼 때부터 응답을 받을 때 까지의 과정을 살펴보자
👏🏻 흔히 면접에서 물어보는 "google.com, naver.com 을 주소창에서 검색할 때 일어나는 일" 을 간략하게 설명하는 것 과 같습니다.
- 사용자는 도메인 이름(api.mysite.com)을 이용하여 웹사이트에 접속한다.
- 이 접속을 위해서는 도메인 이름을 도메인 이름 서비스(DNS)에 질의하여 IP 주소로 변환하는 과정이 필요하다.
- DNS 는 보통 제 3 사업자(third party) 가 제공하는 유료서비스이므로 우리 시스템(단일 서버)의 일부는 아니다.
- DNS 조회로 웹 서버의 IP 주소가 반환된다. (ex 15.123.23.123)
- 해당 IP 주소로 HTTP 요청이 전달된다.
- 요청을 받은 웹 서버는 HTML 페이지나 JSON 형태의 응답을 반환한다.
2. 데이터베이스
- 사용자가 늘면 서버 하나로는 충분하지 않아 여러 서버를 두어야 합니다.
- 하나는 웹/ 모바일 트래픽 처리 용도이고
- 다른 하는 데이터베이스용입니다.
➡️ 2 서버를 분리함으로써 그 각각을 독립적으로 확장해 나갈 수 있게됩니다.
데이터베이스는 크게 관계형 데이터베이스(RDBMS), 비-관계형 데이터베이스 (NoSQL) 2가지로 나눌 수 있다.
RDBMS 란
- 관계형 데이터베이스 관리 시스템 (Relational DataBase Management System)
- 자료를 테이블과 열, 칼럼으로 표현
- SQL을 사용하면 여러 테이블에 있는 데이터를 그 관계에 따라 조인(join) 하여 합칠 수 있다.
NoSql 란
- 비관계형 데이터베이스를 부르는 말
- NoSql은 다시 4가지로 부류로 나눌 수 있다.
- 키-값 저장소 (key-value store), 그래프 저장소 (graph store), 칼럼 저장소 (column store) , 문서 저장소(document store)
- 비- 관계형 데이터베이스는 일반적으로는 조인 연산을 제공하지 않는다.
👏🏻 대체적으로는 RDBMS로 해결할 수 있고 최선일 것인데, 아래와 같은 경우에는 NoSQL이 적절한 선택일 수 있다.
NoSql 이 유용한 상황
- 아주 낮은 응답 지연시간이 요구됨
- 다루는 데이터가 비정형이라 관계형 데이터가 아님
- 데이터를 직렬화하거나 역직렬화할 수 있기만 하면 됨
- 아주 많은 양의 데이터를 저장할 필요가 있음
3. 수직적 규모 확장 vs 수평적 규모 확장
수직적 규모 확장이란 (Scale-up)
- 쉽게말해 서버, 컴퓨터, 저장소 등의 성능 및 크기를 늘리는 일 (물리적으로)
- 단순하지만 무한대로 증설할 수 없다.
- 한대의 서버가 다운될 경우 장애 대응을 할 수 없다는 치명적인 단점을 가지고 있다.
- ✅ 따라서 대규모 애플리케이션을 지원하는 데는 수평적 규모 확장법이 보다 적절하다.
수평적 규모 확장이란 (Scale-out)
- 더 많은 서버를 추가하여 성능을 개선하는 행위
- 너무 많은 사용자(트래픽) 이 몰렸을 때, 서버를 증설하여 트래픽을 분산하는 방법이다.
- 부하 분산기 or 로드 밸런서를 도입하는 방법이다.
1) 로드 밸런서
- 로드밸런서란, 부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할을 한다.
로드밸런서 과정
사용자는 로드밸런서의 공개 IP 주소 (Public IP)로 접속한다.
- 따라서 웹 사버는 클라이언트의 접속을 직접 처리하지 않는다.
- 더 나아가서 서버 간 통신에는 사설 IP (Private IP)가 이용된다.
로드밸런서가 장애를 대응하는 과정
위처럼 스케일 아웃을 통해서 서버를 여러 대로 늘리게 되면 장애를 자동복구하지 못하는 문제 (no failover)도 해소할 수 있고, 웹 계층의 가용성은 향상된다.
- 서버 1이 다운되면 모든 트래픽이 서버 2로 전송된다.
- 따라서 전체 웹사이트가 다운되는 일이 방지된다.
- 부하를 나누기 위해 새로운 서버를 추가할 수 도 있다.
- 웹사이트로 유입되는 트래픽이 가파르게 증가하면 두 대의 서버로 트래픽을 감당할 수 없는 시점이 오는데, 로드밸런서가 있으므로 우아하게 대처할 수 있다.
- 웹 서버 계층에 더 많은 서버를 추가하기만 하면 된다.
- 그러면 로드밸런스가 자동적을 트래픽을 분산 처리한다.
2) 데이터베이스 다중화
DB Replication 이라고도 한다.
- 데이터베이스를 Master(주)-Slave(부)로 나누는데 쓰기 연산은 Master에서만 지원하고, 읽기 연산은 Slave에서만 지원한다.
- 대부분의 애플리케이션에서는 쓰기 작업 보다는 읽기 작업이 훨씬 많기 때문에 Slave 데이터베이스가 훨씬 많다.
데이터베이스 다중화의 장점
- 더 나은 성능
- 모든 데이터 변경 연산은 Master 서버로만 전달되는 반면 읽기 연산은 Slave 데이터베이스 서버들로 분산된다.
- 병렬로 처리될 수 있는 쿼리의 수가 늘어나므로 성능이 좋아진다.
- 안전성
- 데이터베이스 서버 가운데 일부가 파괴되어도 데이터는 보존될 것이다.
- 데이터를 지역적으로 떨어진 여러 장소에 다중화 시켜놓을 수 있기 때문이다.
- 가용성
- 데이터를 여러 지역에 복제해 둠으로써, 하나의 데이터베이스 서버에 장애가 발생하더라도 다른 서버에 있는 데이터를 가져와 계속 서비스할 수 있게 된다.
로드밸런서와 데이터베이스 다중화를 고려한 시스템 설계안
- 사용자는 DNS로부터 로드밸런서의 공개 IP 주소를 받는다.
- 사용자는 해당 IP 주소를 사용해 로드밸런서에 접속한다.
- HTTP 요청은 서버 1이나 서버 2로 전송된다.
- 웹 서버는 사용자의 데이터를 부 데이터베이스 서버에서 읽는다.
- 웹 서버는 데이터 변경 연산은 주 데이터베이스로 전달한다.
4. 캐시 (Cache)
캐시는 응답시간을 개선하는 방법이다.
응답시간을 개선하기 위해서는 캐시를 붙이고 정적 콘텐츠를 콘텐츠 전송 네트워크 (CDN) 으로 옮기면 개선할 수 있다.
👏🏻 어플리케이션의 성능은 데이터베이스를 얼마나 자주 호출하느냐에 크게 좌우되는데, 캐시가 이 문제를 완화할 수 있다.
1) 캐시 계층
캐시 계층은 데이터가 잠시 보관되는 곳으로 데이터베이스보다 훨씬 빠르다.
- 별도의 캐시 계층을 두면 데이터베이스의 부하를 줄일 수 있고, 독립적인 확장이 가능하다.
캐시계층의 요청 처리 과정
- 요청을 받은 웹 서버는 캐시에 응답이 저장되어 있는지를 확인한다.
- 만일 저장되어 있다면 해당 데이터를 클라이언트에 반환한다.
- 없는 경우에는 데이터베이스 쿼리를 통해 데이터를 찾아 캐시에 저장한 뒤 클라이언트에 반환한다.
캐시 사용 시 유의할 점
- 캐시는 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어난다면 고려해볼만 하다.
- 영속적으로 보관할 데이터를 캐시에 두는 것은 바람직하지 않다.
- 캐시는 데이터를 휘발성 메모리에 두기 때문에, 캐시 서버가 재시작되면 모든 데이터는 사라진다.
- 만료된 데이터는 캐시에서 삭제되어야 한다.
- 만료 기한에 대한 정책을 마련하는 것이 좋다.
- 만료 기한이 너무 짧으면, 데이터베이스를 너무 자주 읽게 되며, 너무 길면 원본과 차이가 날 가능성이 높아진다.
- 데이터 저장소의 원본과 캐시 내의 사본 일관성을 확인해야 한다.
- 캐시 서버를 한 대만 두는 경우 해당 서버는 단일 장애 지점(SPOF)이 되어 버릴 수 있다.
- 캐시 메모리 크기는 너무 크지도 작지도 않게 적절하게 잡아야 한다.
- 캐시가 꽉 차버리면 LRU, LFU, FIFO 같은 데이터 방출 정책들을 사용해서 기존 데이터를 내보내야 한다.
5. 콘텐츠 전송 네트워크 - CDN
CDN은 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크이다. 이미지, 비디오, CSS, JavaScript 파일 등을 캐시할 수 있다.
정적 파일들 (front 파일들) 을 정적인 저장소에 지리적으로 분산하여, 두는 방법이다.
자세한 내용은 이전 블로그 정리 글에서! [AWS] CloudFront CDN서비스를 이용해서 Front 구성하기
6. 무상태 웹 계층 (stateless)
사용자의 상태 정보를 웹 계층에서 제거하여 웹 계층을 수평적으로 확장하는 방법이다.
http 프로토콜이 무상태성 특징을 가집니다.
이것에 대해 궁금하시다면 책의 내용보다는 rest api 에 대해서 공부해 보시는 걸 추천드립니다.
[Restful api 란] - 진짜 Rest API 란 무엇이고 어떻게 써야하는 걸까?
7. 데이터센터
- 여러분의 웹사이트가 엄청나게 성장하여 전 세계적으로 사용자가 증가한다면 데이터센터는 필수입니다.
- 장애가 없는 상황에서 사용자는 가장 가까운 데이터 센터로 안내되는데, 통상 이 절차를 지리적 라우팅이라고 부릅니다.
- 만약 데이터 센터 중 하나에 심각한 자애가 발생하면 모든 트래픽은 장애가 없는 데이터 센터로 전송된다.
- 22.10.15 카카오 데이터센터에서 화재가 나 2일간 카카오톡 서비스가 장애가 난 대규모 사태가 있었죠 ㄷㄷ (잡담임다)
다중 데이터센터 아키텍쳐를 만들기위한 기술적 난제
- 트래픽 우회
- 올바른 데이터 센터로 트래픽을 보내는 효과적인 방법을 찾아야 합니다.
- 데이터 동기화
- 데이터 센터마다 별도의 데이터베이스를 다중화하기
- 테스트와 배포
- 여러 위치에서 애플리케이션을 테스트 해보고, 자동화 배포가 모든 데이터 센터에 동일하게 설치되도록 하는 것이 중요합니다.
8. 메시지 큐
- ✨ 메시지 큐는 메세지의 무손실(메시지 큐에 일단 보관된 메시지는 소비자가 꺼낼 때 까지는 안전하다.) 을 보장하는 비동기 통신을 지원하는 컴포넌트 입니다.
메세지 큐 기본 아키텍쳐 (과정)
- 생성자 (Publish/Producer) 는 메세지 큐에 발행한다.
- 큐에는 보통 소비자 (Consumer/Subscribe) 가 메세지를 꺼내서 동작을 수행한다.
메세지 큐의 장점
메시지 큐를 이용하면 시븟 또는 서버 간 결합이 느슨해져서, 규모 확장성이 보장되어야 하는 안정적 어플리케이션을 구성하기 좋습니다.
- 생산자는 소비자 프로세스가 다운되더라도 메시지를 발행할 수 있음
- 소비자는 생산자 서비스가 가용가능한 상태가 아니더라도 메시지를 수신할 수 있음
- 시간이 매우 오래걸리는 사진 보정같은 작업들이 비동기적으로 처리되는 메시지큐 작업의 좋은 예시입니다.
9. 데이터베이스의 규모 확장 (샤딩)
저장할 데이터가 많아지면 데이터베이스에 대한 부하도 증가한다. 이 때도 애플리케이션 서버처럼 스케일 업, 스케일 아웃 두 가지 방법이 존재한다.
✨ 1) 샤딩
- 데이터베이스의 수평적 확장을 위한 방법입니다.
- 샤딩은 대규모 데이터베이스를 샤드(shard) 라고 부르는 작은 단위로 분할하는 기술을 말합니다.
- 샤딩 전략을 구현할 때 중요한 것은 샤딩 키 이고, 샤딩 키에 따라서 한 곳으로만 부하가 집중될 수 있고 여러 곳으로 적절히 잘 분산될 수도 있다.
샤딩을 위해서 고려해야 할 조건
- 데이터의 재 샤딩
- 데이터가 너무 많아져서 하나의 샤드로는 더 이상 감당하기 어려울 때
- 샤드 간 데이터 분포가 균등하지 못하여 어떤 샤드에 할당된 공간 소모가 다른 샤드에 비해 빨리 진행될 때
- 유명 인사
- 핫스팟 키 문제라고도 부르는데, 특정 샤드에 쿼리가 집중되어 서버에 과부하가 걸리는 문제
- 조인과 비정규화
- 일단 하나의 데이터베이스를 여러 샤드 서버로 쪼개고 나면, 여러 샤드에 걸친 데이터를 조인하기가 힘들어진다.
- 이를 해결하는 한 가지 방법은 데이터베이스를 비정규화하여 하나의 테이블에서 쿼리가 수행될 수 있도록 하는 것이다.
🤔 샤딩과 파티셔닝의 차이점
- 파티셔닝이란 퍼포먼스(performance), 가용성(availability) 또는 정비용이성(maintainability)를 목적으로 당신의 논리적인 데이터 엘리먼트들을 다수의 엔티티(table)로 쪼개는 행위를 뜻하는 일반적인 용어이다.
- 샤딩은 수평 파티셔닝(horizontal partitioning)과 동일하다.
- 데이터베이스를 샤딩하게 되면 기존에 하나로 구성될 스키마를 다수의 복제본으로 구성하고 각각의 샤드에 어떤 데이터가 저장될지를 샤드키를 기준으로 분리한다.
- 예를 들면, 나는 고객의 데이터베이스를 CustomerId를 샤드키로 사용하여 샤딩하기로 하였다. 0 ~ 10000 번 고객의 정보는 하나의 샤드에 저장하고 10001 ~ 20000 번 고객의 정보는 다른 샤드에 저장하기로 하였다. DBA는 데이터 엑세스 패턴과 저장 공간 이슈(로드의 적절한 분산 , 데이터의 균등한 저장)를 고려하여 적절한 샤드키를 결정하게 된다.
- 수직 파티셔닝(vertical partitioning)은 하나의 엔티티에 저장된 데이터들을 다수의 엔티티들로 분리하는것을 말한다.
- (마찬가지로 공간이나 퍼포먼스의 이유로) 예를 들면, 한 고객은 하나의 청구 주소를 가지고 있을 수 있다.
- 그러나 나는 데이터의 유연성을 위해 다른 데이터베이스로 정보를 이동하거나 보안의 이슈등을 이유로 CustomerId를 참조하도록 하고 청구 주소 정보를 다른 테이블로 분리할 수 있다.
- 요약하면 파티셔닝은 퍼포먼스, 가용성, 정비용이성등의 목적을 위해 논리적인 엔티티들을 다른 물리적인 엔티티들로 나누는것을 의미하는 일반적인 용어이다.
- 📌 수평 파티셔닝 또는 샤딩은 스키마 복제 후 샤드키를 기준으로 데이터를 나누는것을 말한다.
- 📌 수직 파티셔닝은 스키마를 나누고 데이터가 따라 옮겨가는것을 말한다.
끝!!
참고
'📗 개발자 책 읽기 > 가상 면접 사례로 배우는 대규모 시스템 설계 기초' 카테고리의 다른 글
[System Design Interview] 06. ⚙️ 키-값 저장소 (비 관계형 데이터베이스) 설계하기(1) - CAP 이론 정리 (2) | 2023.01.16 |
---|---|
[System Design Interview] 05. ⚙️ 안정해시란? (0) | 2023.01.10 |
[System Design Interview] 04. 트래픽 처리율 제한 장치의 설계 (rate limiter)❗️❗️ (2) | 2023.01.06 |
[System Design Interview] 03. 시스템 설계 면접 공략법 ❗️ (0) | 2022.12.29 |
[System Design Interview] 02. 개략적인 규모 측정 (0) | 2022.12.28 |