nonneng.ee
Daeun-rithm
nonneng.ee
전체 방문자
오늘
어제
  • 분류 전체보기 (51)
    • Back-end (17)
      • Server (3)
      • Database (3)
      • Spring (9)
      • Node.js (1)
    • Book (1)
      • 이펙티브 자바 (0)
      • 대규모 시스템 설계 (1)
    • Algorithm (1)
      • Greedy, Implementation (6)
      • Dynamic Programming (5)
      • Data Structure (3)
      • Sorting (2)
      • Concept (1)
    • TIL (11)
    • Software (3)
      • Design Pattern (3)
    • Computer Science (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 아이템 23
  • 가상머신
  • 수동설치
  • jwt
  • Java
  • JPA
  • Restful API
  • 아이템8
  • 서버
  • MySQL
  • 컴파일설치
  • API
  • 구현
  • 파이썬
  • 아이템9
  • 아이템 25
  • 아이템6
  • Spring
  • 백준
  • 우분투
  • 소스설치
  • 이펙티브 자바
  • 자바
  • DP
  • APM
  • Postman
  • 에러
  • 구동원리
  • node js
  • 브루트포스

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
nonneng.ee

Daeun-rithm

[대규모 시스템 설계 기초] ch1. 사용자 수에 따른 규모 확장성
Book/대규모 시스템 설계

[대규모 시스템 설계 기초] ch1. 사용자 수에 따른 규모 확장성

2024. 1. 25. 04:49

본문은 '가상 면접 사례로 배우는 대규모 시스템 설계 기초’를 읽고 정리한 내용을 기반으로 작성된 글입니다.

[단일 서버]

☑️ 단일 서버 구성에서의 사용자 요청 처리 흐름

  1. 사용자는 도메인 이름(api.site.com)을 통해 웹사이트에 접속함
    • 이 접속을 위해서는 도메인 이름을 DNS(Domain Name Service)에 질의하여 IP주로 변환하는 과정 필요
    • DNS는 보통 제 3사업자(third party) ↔ 우리 시스템의 일부는 아님
  2. DNS 조회 결과로 IP주소 반환 (15.123 …)
  3. 해당 IP주소로 HTTP(HyperText Transfer Protocol) 요청이 전달됨
  4. 요청을 받은 웹 서버는 HTML페이지나 JSON형태의 응답 반환

 

[데이터베이스]

사용자가 늘면 서버 하나로는 충분하지 않아서 여러 서버를 두어야 한다.

  • 웹/모바일 트래픽 처리 용도
  • 데이터베이스용

 

☑️ 관계형 데이터베이스(RDBMS)

  • 여러 테이블의 데이터를 관계에 따라 조인(join)하여 합칠 수 있음

 

☑️ 비-관계형 데이터베이스(NoSQL)

대부분의 개발자에게는 관계형이 최선일 것이지만,,

  • 아주 낮은 응답 지연시간이 요구되는 경우
  • 다루는 데이터가 비정형이라 관계형이 아닌 경우
  • 데이터를 직렬화, 역직렬화 할 수 있기만 하면 되는 경우
  • 아주 많은 양의 데이터를 저장할 필요가 있는 경우

NoSQL이 바람직한 선택일 수 있다.

 

[수직적 규모 확장 vs 수평적 규모 확장]

‘스케일 업(scale up)’ ↔ 수직적 규모 확장 : 서버에 고사양 자원(CPU, RAM 등)을 추가하는 행위

‘스케일 아웃(scale out)’ ↔ 수평적 규모 확장 : 더 많은 서버를 추가하여 성능을 개선하는 행위

서버로 유입되는 트래픽 양이 적을 때는 수직적 확장이 좋고 단순하다. 그러나

  • 수직적 규모 확장은 한계가 있음 (무한대로 CPU나 메모리 증설 불가)
  • 수직적 규모 확장은 장애에 대한 자동복구(failover) 방안이나 다중화(re-dundancy) 방안을 제시하지 않음 → 서버 장애가 발생하면 서비스는 완전히 중단된다.

따라서 대규모 애플리케이션을 지원하는 데는 수평적 규모 확장법이 보다 적절하다.

 

[로드밸런서]

: 부하 분산 집합(load balancing set)에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할을 한다.

웹 서버가 다운되거나 사용자 증가로 서버가 한계 상황에 도달 → 웹 서버 다운, 접속 불가 문제를 해결하기 위해 도입하는 것이 최선이다.

  • 사용자는 로드밸런서의 공개 IP주소로 접근함
    • 웹 서버는 클라이언트의 접속을 직접 처리하지 않음
    • 서버 간 통신에는 사설 IP주소가 이용됨
      • 사설 IP주소 ↔ 같은 네트워크에 속한 서버 사이의 통신에만 쓰이는 주소
  • 서버1이 다운되면 → 모든 트래픽은 서버2로 전송됨
  • 웹 서버 계층에 더 많은 서버를 추가하기만 하면 로드밸런스가 자동적으로 트래픽을 분산하기 시작한다.

그렇다면 데이터 계층은??

 

[데이터베이스 다중화]

: 보통은 서버 사이에 주(master)-부(slave) 관계를 설정하고, 데이터 원본은 주 서버, 사본은 부 서버에 저장하는 방식

  • 쓰기 연산은 마스터에서만 지원
  • 부 데이터베이스는 읽기 연산만 지원

 

☑️ 데이터베이스 다중화로 얻는 이득

  • 성능 : 병렬로 처리될 수 있는 질의(query)수가 늘어남
  • 안정성 : 데이터베이스 서버 일부가 파괴되어도 데이터는 보존됨
  • 가용성 : 데이터를 여러 지역에 복제해 둠 → 서버 장애가 생겨도 계속 서비스 가능

 

☑️ 주 데이터베이스 서버가 다운되면?

  • 부 데이터베이스가 한 대
    • 해당 부 데이터베이스 서버가 새로운 주 서버가 됨
    • 새로운 부 데이터서버가 추가됨

사실 프로덕션 환경에서는 부 데이터서버의 데이터가 최신이 아니기 때문에 훨신 복잡함 ↔ 복구 스크립트 (다중 마스터, 원형 다중화 방식 도입)

 

☑️ 로드밸런서와 데이터베이스 다중화를 고려한 설계안

  1. 사용자는 DNS로부터 로드밸런서의 공개 IP주소를 받음
  2. 사용자는 해당 IP주소를 사용해 로드밸런서에 접속
  3. HTTP 요청은 서버1, 서버2로 전달됨
  4. 웹 서버는 사용자의 데이터를 부 데이터베이스 서버에서 읽음
  5. 웹 서버는 데이터 변경 연산 → 주 데이터베이스로 전달함

이제 응답시간을 개선해보자.

 

[캐시]

응답시간은 캐시(cache)를 붙이고 정적 콘텐츠를 콘텐츠 전송 네트워크(Content Delivery Network, CDN)로 옮기면 개선할 수 있다.

 

☑️ 캐시

: 값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고, 뒤이은 요청이 보다 빨리 처리될 수 있도록 하는 저장소

애플리케이션의 성능은 데이터베이스를 얼마나 자주 호출하느냐에 크게 좌우됨 ↔ 캐시는 이 문제를 완화 가능

 

☑️ 캐시 계층

: 데이터가 잠시 보관되는 곳 → 데이터베이스보다 훨씬 빠르다.

별도의 계층을 둠 → 성능 개선, DB부하 감소, 캐시 계층 규모의 독립적 확장 가능

 

[읽기 주도형 캐시 전략]

  1. 요청을 받은 웹 서버 → 캐시에 응답이 저장되어 있는지 확인
  2. 있다면 해당 데이터를 클라에게 반환
  3. 없다면 데이터베이스 질의를 통해 데이터를 찾아 캐시에 저장한 뒤 클라에게 반환

읽기 주도형 외에도 다양한 전략이 있음

 

☑️ 캐시 사용 시 유의할 점

Q : 어떤 상황에 바람직한가?

A : 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어나는 상황

 

Q : 캐시에 보관된 데이터는 어떻게 만료(expire)되는가?

A : 영속적으로 보관할 데이터 제외

 

Q : 일관성(consistency)은 어떻게 유지되는가?

A : 트랜잭션 관리, 자동 업데이트 메커니즘 등

 

Q : 장애에는 어떻게 대처할 것인가?

A : 여러 지역에 걸쳐 캐시 서버 분산하기

 

Q : 캐시 메모리는 얼마나 크게 잡을 것인가?

A : 과할당하는게 좋다

 

Q : 데이터 방출(eviction) 정책은 무엇인가?

A : LRU(Least Recently Used), LFU(Least Frequently Used), FIFO(First In First Out) 등등

 

[콘텐츠 전송 네트워크(CDN)]

: 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크 ↔ 이미지, 비디오, CSS, JavaSrcipt 파일 등을 캐시

사용자가 웹사이트 방문 → 그 사용자에게 가장 가까운 CDN 서버가 정적 콘텐츠를 전달

 

☑️ CDN 동작 과정

  1. 사용자 A가 이미지 URL을 통해 이미지에 접근함 (URL의 도메인은 CDN 서비스 사업자가 제공)
  2. CDN 서버의 캐시에 해당 이미지가 없는 경우, 원본 서버에 요청하여 파일을 가져옴
  3. 원본 서버가 파일을 CDN 서버에 반환하고, 응답의 HTTP 헤더에는 TTL값도 같이 반환
  4. CDN 서버는 파일을 캐시하고 사용자에게 반환함 → 이미지는 TTL에 명시된 시간이 끝날 때까지 캐시됨
  5. 사용자 B가 CDN 서버에 요청 → 만료되지 않은 이미지에 대한 요청은 캐시를 통해 처리된다.

 

☑️ CDN 사용 시 고려해야 할 사항

  • 비용 : CDN은 보통 제3 사업자(third-party providers)에 의해 운영되기 때문
  • 적절한 만료 시한 설정 : 너무 길면 콘텐츠의 신선도가 떨어지고, 너무 짧으면 원본 서버에 빈번히 접속해야 함
  • CDN 장애에 대한 대처 방안 : CDN 자체가 죽었을 경우 동작방안
  • 콘텐츠 무효화 : 만료되지 않은 콘텐츠라도 제거할 수 있어야 함

 

☑️ CDN과 캐시가 추가된 설계

 

[무상태(stateless) 웹 계층]

웹 계층을 수평적으로 확장하려면 상태 정보(사용자 세션 데이터 같은)를 웹 계층에서 제거해야 한다.

: 상태 정보를 관계형 데이터베이스나 NoSQL같은 지속성 저장소에 보관하는 웹 계층

 

☑️ 상태 정보 의존적인 아키텍처

: 클라이언트 정보(상태)를 유지하여 요청들 사이에 공유되도록 함

문제점 : 같은 클라이언트로부터의 요청은 항상 같은 서버로 전송되어야 함

 

☑️ 무상태 아키텍처

  • 사용자로부터의 HTTP 요청은 어떤 웹 서버로도 전달될 수 있음
  • 상태 정보가 필요한 경우 공유 저장소로부터 데이터를 가져옴
  • 상태 정보, 웹 서버가 물리적으로 분리되어 있음 → 단순, 안정적, 규모확장이 쉬움

 

☑️ 무상태 웹 계층을 갖도록 설계 변경

상태 정보가 웹 서버들로부터 제거됨 → 트래픽 양에 따라 웹 서버를 넣거나 빼기만 하면 자동으로 규모 확장 가능

 

[데이터 센터]

웹사이트가 매우 빨리 성장하여 전 세계 사용자의 이목을 받는 경우,

가용성을 높이고 전 세계 어디서도 쾌적하게 사용할 수 있도록 하기 위해 여러 데이터 센터를 지원하는 것이 필수다.

☑️ 지리적 라우팅

: 사용자를 가장 가까운 데이터 센터로 안내해주는 절차

 

☑️ 기술적 난제

  • 트래픽 우회 : 올바른 데이터 센터로 트래픽을 보내는 효과적 방법 찾기
  • 데이터 동기화 : 장애가 생겼을 때 → 트래픽 우회 → 다른 데이터센터에도 찾는 데이터가 있어야 함
  • 테스트와 배포 : 여러 위치에서 테스트하고, 모든 데이터 센터에 동일한 서비스가 설치되도록 배포해야 함

 

[메시지 큐]

: 메시지의 무손실을 보장하는 비동기 통신을 지원하는 컴포넌트

↔ 메시지 큐에 일단 보관된 메시지는 소비자가 꺼낼 때까지 안전히 보관됨을 보장함

→ 서비스 또는 서버 간 결합이 느슨해져서, 규모 확장성에 용이함

 

☑️ 메시지 큐의 기본 아키텍쳐

  • 생산자 또는 발행자(producer/publisher)가 메시지를 만들어 메시지 큐에 발행함
  • 소비자 혹은 구독자(consumer/subscriber)가 메시지를 받아 그에 맞는 동작 수행

생산자/발행자 ↔ 입력 서비스

소비자/구독자 ↔ 서비스, 서버

 

[로그, 메트릭 그리고 자동화]

: 규모가 커지면 필수적으로 투자해야 하는 도구

 

[데이터베이스의 규모 확장]

[수직적 확장(scale-up)]

☑️ 수직적 접근법의 심각한 약점

  • DB 서버의 CPU, RAM등을 무한 증설할 순 없음 → 결국에는 한 대로는 감당하기 어렵게 됨
  • SPOF(Single Point Of Failure)로 인한 위험성이 크다.
  • 고성능 서버일수록 비용이 많이 든다.

 

[수평적 확장]

☑️ 샤딩

: DB를 샤드(shard)라고 부르는 작은 단위로 분할하는 기술 ↔ DB의 수평적 확장

  • 모든 샤드는 같은 스키마를 쓰지만, 샤드에 보관되는 데이터 사이에는 중복이 없음
  • ex) 4개의 샤드 ↔ (user_id % 4)를 해시 함수로 사용하여 데이터가 보관되는 샤드를 정함

 

☑️ 샤딩에서 고려할 부분

  • 샤딩 키를 어떻게 정하느냐 !!
    • 데이터가 어떻게 분산될지 정하는 하나 이상의 칼럼(ex. user_id)
    • 데이터를 고르게 분할할 수 있도록 하는 게 중요함
  • 데이터의 재 샤딩
    • 하나의 샤드로는 감당하기 어려울 때
    • 데이터 분포가 균등하지 못할 때
  • 유명인사 문제
    • ㅋㅋㅋ
  • 조인과 비정규화
    • 하나의 DB를 여러개로 쪼개면, 여러 샤드에 걸친 데이터를 조인하기 힘들다 → DB를 비정규화하여 하나의 테이블에서 질의가 수행되도록 한다.
    • ex) 인덱싱 추가, 요약 테이블 추가

☑️ 샤딩 + 여러 도구들을 적용한 아키텍쳐

정리하면,

  • 웹 계층은 무상태 계층으로
  • 모든 계층에 다중화 도입
  • 가능한 한 많은 데이터 캐시
  • 여러 데이터 센터 지원
  • 정적 콘텐츠는 CDN을 통해 서비스
  • 데이터 계층은 샤딩을 통해 규모 확장
  • 각 계층은 독립적 서비스로 분할
  • 시스템 지속적 모니터링, 자동화 도구 활용

재밌다~

 


 

    nonneng.ee
    nonneng.ee

    티스토리툴바