1장 : 사용자 수에 따른 규모 확장성
Last updated
Last updated
모든 컴포넌트가 단 한 대의 서버에서 실행되는 간단한 시스템부터 설계해 보자.
웹 앱, 데이터베이스, 캐시 등이 전부 한 대에서 실행된다.
웹 애플리케이션
비즈니스 로직, 데이터 저장 등을 처리하기 위해서는 서버 구현용 언어(자바, 파이썬 등)를 사용하고, 프레젠테이션용으로는 클라이언트 구현용 언어(HTML, 자바스크립트 등)를 사용한다.
모바일 앱 : 모바일 앱과 웹 서버 간 통신을 위해서는 HTTP 프로토콜을 이용하낟. HTTP 프로토콜을 통해서 반환될 응답 데이터의 포맷으로는 보통 JSON(JavaScript Object Notation)이 그 간결함 덕에 널리 쓰인다.
어떤 데이터베이스를 사용할 것인가 ?
RDBMS
MySQL, 오라클 데이터베이스, PostgreSQL
join을 통해 테이블에 있는 데이터를 합칠 수 있음
NoSQL
CouchDB, Neo4j, Cassandra, HBase, Amazon DynamoDB
키-값 저장소, 그래프 저장소, 칼럼 저장소, 문서 저장소
일반적으로 join 연산 지원 x
사용 경우
아주 낮은 응답 지연시간(latency)이 요구됨
다루는 데이터가 비정형(unstructured)이라 관계형 데이터가 아님
데이터(JSON, YAML, XML 등)를 직렬화하거나(serialiize) 역직렬화(deserialize)할 수 있기만 하면 됨
아주 많은 양의 데이터를 저장할 필요가 있음
수직적 확장의 단점
한 대의 서버에 CPU나 메모리를 무한대로 증성할 방법이 없다.
자동복구 방안이나 다중화 방안을 제시하지 않는다.
로드밸런서
부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산한다.
데이터베이스 다중화
서버 사이에 주(master)-부(slave) 관계를 설정하고 데이터 원본은 주서버에, 사본은 부 서버에 저장하는 방식이다.
더 나은 성능
안정성(realiability)
가용성(availabilty)
다음은 로드밸런서와 DB 다중화를 고려한 설계안이다. 여기서 응잡시간(latency)은 캐시(cache)를 붙이고 정적 콘텐츠를 콘텐츠 전송 네트워크(Content Delivery Network, CDN)로 옮기면 개선할 수 있다.
캐시는 값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고, 뒤이은 요청이 보다 빨리 처리될 수 있도록 하는 저장소다. 애플리케이션의 성능은 데이터베이스를 얼마나 자주 호출하느냐에 크게 좌우되는데, 캐시는 그런 문제를 완화할 수 있다.
캐시 계층
데이터가 잠시 보관되는 곳으로 데이터베이스보다 훨씬 빠르다.
캐시 사용 시 유의할 점
캐시는 데이터 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어나는 상황에서 고려해볼 만하다.
캐시는 데이터를 휘발성 메모리에 두므로, 영속적으로 보관할 데이터를 캐시에 두는 것은 바람직하지 않다.
캐시에 보관된 데이터의 만료에 관한 정책을 마련해두어야 한다.
일관성은 데이터 저장소의 원본과 캐시 내 사본이 같은지 여부다. ScalingMemchae at Facebook
캐시 서버를 한 대만 두는 경우 해당 서버는 단일 장애 지점(SPOF)이 되어버릴 가능성이 있다. 이를 피하려면 여러 지역에 걸쳐 캐시 서버를 분산시켜야 한다.
캐시 메모리는 과할당해서 잡다.
데이터 방출 정책 중 가장 널리 쓰이는 것은 LRU(Least Recently Used)이며, LFU(Least Frequently Used)와 FIFO(FIrst In First Out) 같은 것도 있다.
CDN은 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크이다. 이미지, 비디오, CSS, JavaScript 파일 등을 캐시할 수 있다.
다음은 CDN과 캐시가 추가된 설계다.
웹 계층을 수평적으로 확장해보자. 이를 위해서는 상태 정보(사용자 세션 데이터와 같은)를 웹 계층에서 제거하여야 한다. 바람직한 전략은 상태 정보를 관계형 데이터베이스나 NoSQL 같은 지속성 저장소에 보관하고, 필요할 때 가져오도록 하는 것이다. 이렇게 구성된 웹 계층을 무상태 웹 계층이라 부른다.
상태 정보 의존적인 아키텍처
무상태 아키텍처
다음은 무상태 웹 계층을 갖도록 기존 설계를 변경한 것이다.
다음은 두 개의 데이터 센터를 이용하는 사례다. 장애가 없는 상황에서 사용자는 가장 가까운 데이터 센토로 안내되는데, 통상 이 절차를 지리적 라우팅이라고 부른다.
다중 데이터센터 아키텍처를 만들려면 몇 가지 기술적 난제를 해결해야 한다.
트래픽 우회
데이터 동기화
테스트와 배포
시스템을 더 큰 규모로 확장하기 위해서는 시스템의 컴포넌트를 분리하여, 각기 독립적으로 확장될 수 있도록 하여야 한다.
메시지 큐는 메시지의 무손실(durability, 즉 메시지 큐에 일단 보관된 메시지는 소비자가 꺼낼 때까지 안전히 보관된다는 특성)을 보장하는, 비동기 통신(asynchronous communication)을 지원하는 컴포넌트다. 메세지의 버퍼 역할을 하며, 비동기적으로 전송한다.
메시지큐늬 기본 아키텍처
생산자 또는 발행자(producer/publisher)라고 불리는 입력 서비스가 메시지를 만들어 메시지 큐에 발행(publish)한다.
큐에는 보통 소비자 혹은 구독자(consumer/subscriber)라 불리는 서비스 혹은 서버가 연결되어 있는데, 메시지를 받아 그에 맞는 동작을 수행하는 역할을 한다.
메시지 큐를 이용하면 서비스 또는 서버 간 결합이 느슨해져서, 규모 확장성이 보장되어야 하는 안정적 애플리케이션을 구성하기 좋다.
메시지 큐, 로그, 메트릭, 자동화 등을 반영하여 수정한 설계안
로그 :
시스템의 오류와 문제들을 보다 쉽게 찾아낼 수 있도록 하기 때문이다.
메트릭 :
호스트 단위 메트릭 : CPU, 메모리, 디스크 I/O에 관한 메트릭이 여기 해당한다.
종합(aggregated) 메트릭 : 데이터베이스 계층의 성능, 캐시 계층의 성능 같은 것이 여기 해당한다.
핵심 비즈니스 매트릭 : 일별 능동 사용자(daily active user), 수익(revenue), 재방문(retention) 같은 것이 여기 해당한다.
자동화 :
시스템이 크고 복잡해지면 생산성을 높이기 위해 자동화 도구를 활용해야 한다.
수직적 확장
기존 서버에 더 많은, 또는 고성능의 자원(CPU, RAM, 디스크 등)을 증설하는 방법이다.
수평적 확장
데이터베이스의 수평적 확장은 샤딩(sharding)이라고도 부르느데, 더 많은 서버를 추가함으로써 성능을 향상시킬 수 있도록 한다.
샤딩은 대규모 데이터베이스를 샤드(shard)라고 부르는 작은 단위로 분할하는 기술을 일컫는다. 모든 샤드는 같은 스키마를 쓰지만 샤드에 보관되는 데이터 사이에는 중복이 없다.
웹 계층은 무상태 계층으로
모든 계층에 다중화 도입
가능한 한 많은 데이터를 캐시할 것
여러 데이터 센터를 지원할 것
정적 콘텐츠는 CDN을 통해 서비스할 것
데이터 계층은 샤딩을 통해 그 규모를 확장할 것
각 계층은 독립적 서비스로 분할할 것
시스템을 지속적으로 모니터링하고, 자동화 도구들을 활용할 것