Read Book/대규모 시스템 설계 기초

1장. 사용자 수에 따른 규모 확장성

nowwater 2023. 8. 3. 19:24
728x90

데이터베이스

처리해야 할 데이터에 따라 RDBMS, NoSQL 을 선택적으로 활용 가능

비관계형 데이터베이스 에러 복구(failover) 방안이나 다중화(redundancy) 방안을 제시하지 않음

  • 서버 장애 시 웹사이트/앱은 완전히 중단됨

스케일아웃: 더 많은 서버를 추가하여 성능 개선 - 수평적 규모 확장

  • 스케일 업의 이러한 단점들 때문에 대규모 애플리케이션 지원 시에는 스케일 아웃이 적절하다

 

로드밸런서

부하 분산 집합에 속한 웹 서버들에게 트래픽 부하를 고르게 분산하는 역할

사용자는 로드밸런서의 공개 IP 주소로 접속하고, 서버 간 통신에는 사설 IP 주소가 이용된다.

부하 분산 집합에 웹 서버를 추가한 후 로드밸런서를 통해 골고루 부하를 나눠 갖게 되면, 장애 복구 문제를 해결할 수 있고 웹 계층의 가용성은 향상된다. (트래픽 증가에 따라 웹 서버를 추가)

 

데이터베이스 다중화

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

  • master: 쓰기 연산
  • slave: 읽기 연산

장점

  • 더 나은 성능: 병렬로 처리될 수 있는 질의(query) 수가 늘어나므로 성능이 좋아진다.
  • 안정성: 자연 재해 등의 이유로 데이터베이스 서버 일부가 파괴되어도 데이터 보존 가능
  • 가용성: 여러 지역에 복제해 둠으로써 하나의 데이터베이스 서버에 장애가 나더라도 다른 서버에 있는 데이터를 가져와 서비스 지속 가능

데이터베이스 서버 가운데 하나가 다운되면 ?

부 데이터베이스가 다운될 경우

1)부 데이터베이스가 1대인 경우

  • 읽기 연산은 한시적으로 모두 주 데이터베이스로 전달
  • 즉시 새로운 부 데이터베이스 서버가 장애 서버를 대체
  1. 부 데이터베이스 여러 대인 경우
  • 읽기 연산은 나머지 부 데이터베이스 서버들로 분산
  • 새로운 부 데이터베이스 서버가 장애 서버를 대체

주 데이터베이스가 다운될 경우

1)부 데이터베이스가 1대인 경우

  • 해당 부 데이터베이스 서버가 새로운 주 데이터베이스 서버가 됨
  • 모든 데이터베이스 연산은 일시적으로 새로운 주 서버 상에서 수행
  • 새로운 부 서버가 추가

그러나 부 서버에 보관된 데이터가 최신 상태가 아닐 수 있다

그때는 없는 데이터는 복구 스크립트를 돌려서 추가해야 한다 -> 다중 마스터(multi-masters), 원형 다중화(circular replication) 방식을 도입하면 해결 가능

대부분의 애플리케이션은 읽기 연산의 비중 >> 쓰기 연산의 비중

따라서 부 데이터베이스의 수 > 데이터베이스의 수

 

캐시

값비싼 연산 결과 or 자주 참조되는 데이터를 메모리 안에 저장 후 요청 시 반환

애플리케이션의 성능은 데이터베이스를 얼마나 자주 호출하느냐에 크게 좌우되는데, 그런 문제를 완화시켜줌

별도의 캐시 계층을 두면 성능이 개선되고, 데이터베이스의 부하를 줄일 수 있으며, 캐시 계층의 규모를 독립적으로 확장시킬 수도 있다.

캐시할 데이터 종류, 크기, 액세스 패턴에 따라 다양한 캐시 전략을 활용 가능

유의점

  • 데이터 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어날 경우 고려
  • 휘발성 메모리에 두므로, 영속 보관할 데이터는 저장 X
  • 만료 기한은 너무 짧지도 너무 길게도 설정 X
  • 저장소 원본 갱신 연산과 캐시 갱신 연산을 단일 트랜잭션에서 처리하지 않으면 일관성이 꺠질 수 있다
  • 캐시 서버를 한 대만 두면 단일 장애 지점(SPOF)이 될 수 있다.
    • 어떤 특정 지점에서의 장애가 전체 시스템의 동작을 중단시켜버릴 수 있는 지점
    • SPOF 를 피하려면 여러 지역에 걸쳐 캐시 서버를 분산시켜야 함
  • 캐시 메모리가 너무 작으면 액세스 패턴에 따라서는 eviction 이 자주되어 캐시 성능이 떨어질 수 있다
  • 캐시가 꽉 찰 경우 eviction policy 를 적절히 선정해야 한다

컨텐츠 전송 네트워크(CDN)

정적 콘텐츠를 전송하는데 쓰이는 지리적으로 분산된 서버의 네트워크

사용자가 웹사이트를 방문하면 가장 가까운 CDN 서버가 정적 컨텐츠(이미지, 비디오, CSS, Javascript)를 전달

CDN 이 멀수록 웹사이트 로딩 속도가 느려짐

유의점

  • 비용: 제 3 사업자에 의해 운영되는 CDN 의 비용은 들어가고 나가는 데이터 전송 양에 따라 달라짐
  • 적절한 만료 시한 설정: 너무 길지도 짧지도 않게 설정해야 함
  • 장애 대처 방안: CDN 자체가 죽을 경우 웹사이트/애플리케이션이 어떻게 동작할 지 고려
    • 해당 문제를 감지하여 원본 서버로부터 직접 콘텐츠를 가져오도록 클라이언트 구성하는 방식도 존재
  • 콘텐츠 무효화 방안: 만료되지 않은 컨텐츠를 무효화 시키는 방법 고려
    • CDN 서비스 사업자가 제공하는 API 로 무효화
    • 오브젝트 버저닝: URL 마지막에 버전 번호를 인자로 넘겨주기 (e.g. image.png?v=2)

무상태(Stateless) 웹 계층

웹 계층을 수평적으로 확장하기 위해서는 상태 정보(e.g. 사용자 세션 데이터)를 웹 계층에서 제거 후,

그러한 상태 정보는 데이터 계층에 영속적으로 저장하는 형태

만약 그렇지 않고 상태 정보 의존적인 아키텍처를 사용하게 되면, 서버는 클라이언트 정보를 유지하여 요청들 사이에 공유를 하게 된다.

그러면 같은 클라이언트 요청은 항상 같은 서버로 전달되어야 정상적으로 처리가 가능해지는데, 이렇게 되면 로드밸런서는 고정 세션(sticky session) 이라는 기능을 사용해야해서 부담을 주게 된다.

  • 로드 밸런서는 어느 사용자가 어느 노드에 연결되었는지 기억해야 함.
  • 모든 트래픽에 대해서 세션 → 노드 맵을 탐색하는 비용이 발생한다. (이떄 로드밸런서에 집중적인 부하 발생)

무엇보다도 로드밸런서 뒷단에 서버를 추가하거나 제거하기 까다로워진다는 단점이 있다. 또한 서버의 장애를 처리하기도 복잡해진다.

  • 노드 추가나 제거가 까다로움 → 로드밸런서 재 시작시 노드 리스트가 바뀌니까 세션-노드 맵이 유효하지 않게 될 수 있고, 사용자들 입장에서는 세션이 날아가며 서비스 홈페이지로 튕긴다
  • 노드 장애 발생시 해당 노드에 있는 서버에 접속해 있던 사용자는 에러 응답

무상태 웹 계층을 구성하게 되면 사용자로부터의 HTTP 요청은 어떤 웹 서버로도 전달할 수 있고, 상태 정보가 필요할 경우 웹 서버로부터 물리적으로 분리된 공유 저장소로부터 데이터를 가져올 수 있다.

이렇게 되면 단순하고, 안정적이며, 규모 확장이 쉬운 아키텍처를 만들 수 있다.

상태 정보가 웹 서버들로부터 제거되었으므로, 트래픽 양에 따라 웹 서버를 넣거나 빼기만 하면 자동으로 규모를 확장할 수 있는 용이한 구조가 됨

자동 규모 확장(autoscaling) 기능을 통해 트래픽 양에 따라 웹 서버를 자동으로 추가하거나 삭제 가능

데이터 센터

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

지리적 라우팅(geo-routing): 장애가 없는 상황에서 사용자에게 가장 가까운 데이터 센터로 안내

데이터 센터에 장애 발생 시

모든 트래픽은 장개가 없는 데이터 센터로 전송된다. 아래는 데이터센터2에 장애가 발생하여 모든 트래픽이 데이터센터1로 전송되는 상황의 예

다중 데이터 센터 아키텍처를 만들기 위해 고려해야 할 사항들

  • 트래픽 우회: 올바른 데이터 센터로 트래픽을 보내는 효과적 방법을 찾아야 함(e.g. geo-routing)
  • 데이터 동기화: 데이터를 여러 데이터센터에 걸쳐 다중화
  • 테스트와 배포: 웹 사이트 또는 애플리케이션을 여러 위치에서 테스트해보기

메세지 큐

메시지의 무손실(durability)을 보장하며, 비동기 통신을 지원하는 컴포넌트

즉, 메시지의 버퍼 역할을 하며, 비동기적으로 전송한다.

  • 생산자(발행자) 입력 서비스가 메시지를 만들어 큐에 발행
  • 소비자(구독자) 서비스가 메시지를 받아서 그에 맞는 동작을 수행

장점

각 컴포넌트(서비스) 간 결합이 느슨해져 규모 확장성이 보장되어야 하는 안정적 애플리케이션을 구성하기 좋다.

생산자와 소비자는 독립적으로 메시지 송/수신 가능

 

로그, 메트릭, 자동화

  • 로그: 시스템의 오류와 문제들을 쉽게 찾아낼 수 있게 해줌
  • 메트릭: 사업 현황에 관한 유용한 정보 수집 가능
  • 자동화: 시스템이 크고 복잡해지면 생산성을 높이기 위해 자동화 도구를 활용해야 함 (e.g. 지속적 통합을 도와주는 도구 활용)

데이터베이스의 규모 확장

수직적 확장(스케일 업)

  • 기존 서버에 고성능의 자원(CPU, RAM, 디스크 등) 증설
  • 심각한 약점이 존재함
    • 서버 하드웨어 한계 - 무한 증설 불가능하여 사용자가 계속 늘어날 경우 감당하기 어려워짐
    • SPOF 로 인한 위험 증가
    • 비용이 많이 듦

수평적 확장(샤딩)

  • 더 많은 서버를 추가하여 성능 향상
  • 대규모 데이터베이스를 샤드라고 부르는 작은 단위로 분할
  • 모든 샤드는 같은 스키마 사용하지만 샤드에 보관되는 데이터 사이에는 중복이 없음 -> 샤딩 키를 지정해 어떤 샤드에 데이터를 저장할 지 결정함
  • 샤딩 키는 하나 이상의 컬럼으로 구성되며, 이러한 샤딩 키를 통해 올바른 데이터베이스에 질의를 보내어 데이터 조회/변경을 처리하므로 효율을 높일 수 있음
  • 데이터를 고르게 분할할 수 있도록 샤딩 키를 정하는 것이 가장 중요함
  • 단점
    • 데이터 재샤딩: 샤드 소진이 발생할 때 샤드 키를 계산하는 함수를 변경하고 데이터를 재배치해야 함
      • 데이터가 너무 많아져서 하나의 샤드로 감당하기 힘들 때
      • 샤드 간 데이터 분포가 균등하지 않아서 어떤 샤드에 할당된 공간 소모가 다른 샤드에 비해 빠르게 진행될 때
    • 유명 인사 문제: 핫스팟 키 라고도 불리며, 특정 샤드에 질의가 집중되어 서버에 과부하가 걸리는 문제 발생 가능
    • 조인과 비정규화: 한번 여러 샤드로 쪼개고 나면, 여러 샤드에 걸친 데이터를 조인하기 힘들어짐 -> 데이터베이스를 비정규화하여 하나의 테이블에서 질의가 수행될 수 있도록 하면 해결 가능

 

 

최종 아키텍쳐

처리해야 할 데이터에 따라 RDBMS, NoSQL 을 선택적으로 활용 가능

비관계형 데이터베이스가 바람직한 경우

  • 아주 낮은 응답 지연시간 요구
  • 다루는 데이터가 비정형인 경우
  • 데이터(JSON, YAML, XML 등)를 직렬화하거나 역직렬화 할 수 있으면 되는 경우
  • 아주 많은 양의 데이터를 저장해야할 경우