kimyu0218
  • [가상 면접 사례로 배우는 대규모 시스템 설계 기초] 1장 사용자 수에 따른 규모 확장성
    2024년 11월 21일 16시 00분 44초에 업로드 된 글입니다.
    작성자: @kimyu0218

    시스템 아키텍처를 보면 웹 서버와 DB 서버를 분리한 경우를 많이 볼 수 있다. 사용자 수가 늘어나면 여러 서버를 두게 되는데 이때 웹 서버와 DB 서버를 분리하면 각각 독립적으로 확장할 수 있기 때문이다.

    지금부터 시스템 규모 확장 방법을 알아보자.

     

    수직 확장 vs. 수평 확장 (feat. 수평 확장을 선택해야 하는 이유)

    시스템 확장에는 크게 수직, 수평 확장 두 가지가 있다.

    1. 수직 확장 (scale up) : 고사양 자원을 사용하여 서버의 성능을 높인다
    2. 수평 확장 (scale out) : 더 많은 서버 자원을 추가하여 성능을 높인다

    수직 확장은 쉽게 성능을 향상시킬 수 있지만, 성능 향상에 한계가 있으며 자동 복구(= failover)나 다중화(= redundancy)를 할 수 없다는 단점이 있다. 즉, 아무리 성능이 높은 서버라도 장애가 발생하면 서비스를 이용할 수 없다. 따라서 대규모 어플리케이션에서는 수평 확장이 더 적절하다.

     

    로드밸런서 (ELB)

    웹 서버가 하나인 시스템에서 부하로 인해 서버가 다운되면 사용자는 웹 사이트에 접속할 수 없다. 이를 예방하기 위해 로드밸런서를 사용한다.

    사용자는 로드밸런서의 퍼블릭 ip 주소로 접속한다. 그러면 로드밸런서는 target group에 속한 웹 서버들에게 트래픽 부하를 고르게 분산시킨다. 서버가 죽더라도 target group에 다른 정상적인 서버가 존재한다면 가용성을 보장할 수 있다.

     

    데이터베이스 확장

    데이터베이스 다중화 : master-slave

    이번엔 DB 부하 및 장애를 해결하는 방법을 알아보자. 일반적으로 master-slave 관계를 설정하여 다중화를 구현한다.

    master 서버 slave 서버
    write 연산 read 연산
    데이터 원본 데이터 사본

    write 연산은 오직 master에서만 일어난다. slave는 master로부터 사본을 전달받고 read 연산을 지원한다. 대부분 read 연산이 많기 때문에 slave의 수가 master보다 많다.

     

    master-slave는 다음 장점을 가진다.

    • 성능 : read 연산을 병렬로 처리할 수 있다
    • 안정성 : 일부 서버가 파괴되어도 데이터를 보존할 수 있다
    • 가용성 : 일부 서버에 장애가 발생해도 다른 서버에서 계속 서비스할 수 있다
    🤔 master 서버가 다운되면 무슨 일이 발생할까?
    • slave 서버 중 하나가 새로운 master 서버가 된다.
    • slave 서버의 데이터가 최신 상태가 아닌 경우, 복구 스크립트를 돌려야 한다.

     

    데이터베이스 수평 확장 : 샤딩

    샤딩은 DB를 샤드라는 작은 단위로 분할하는 기술이다. 모든 샤드는 같은 스키마를 쓰지만 서로 다른 데이터를 보관한다.

    샤딩을 구현할 때 가장 중요한 것은 파티션 키(= 샤딩 키)다. 파티션 키는 데이터를 어떻게 분산시킬 지 정한다.

     

    하지만 샤딩을 도입하면 시스템이 복잡해지고 새로운 문제가 생긴다.

    • 데이터가 늘어나면 새로운 샤드를 만들어야 한다. (resharding) 이때 데이터 분포의 불균형이 발생할 수 있다.
    • DB를 여러 샤드로 쪼개기 때문에 여러 샤드에 걸친 JOIN 연산이 어려워진다.
    💡 재샤딩 시 안정 해시를 활용하면 데이터 불균형을 해결할 수 있다.

     

    응답 시간 줄이기 (feat. 캐시 & CDN)

    캐시

    캐시는 메모리 공간이므로 DB보다 훨씬 속도가 빠르다. 따라서 캐시를 두면 DB 부하를 줄일 뿐만 아니라 응답 시간을 개선할 수 있다.

    하지만 캐시를 무분별하게 사용해서는 안된다. 캐시는 휘발성 메모리이기 때문에 영속적인 데이터를 보관해선 안되며, 적절한 만료 기간을 설정하여 공간을 계속 점유하는 것을 막아야 한다. 이외에도 캐시와 영구적인 저장소의 일관성을 보장해야 한다.

    🤔 SPOF; Single Point of Failure
    • 특정 지점에서의 장애가 전체 시스템 동작을 중단시킬 수 있는 경우, 해당 지점을 단일 장애 지점(= SPOF)이라고 한다.
    • 캐시를 사용할 때도 SPOF 문제를 방지하기 위해서는 캐시 서버를 여러 대 두어야 한다.

     

    CDN; Contents Delivery Network

    CDN은 정적 콘텐츠를 전송하는 데 사용되는, 지리적으로 분산된 서버 네트워크다. 사용자가 CDN을 사용하는 웹사이트에 방문하면, 사용자와 가장 가까운 CDN 서버가 정적 콘텐츠를 전달한다. 사용자와 가까울수록 응답 속도는 빨라진다.

     

    하지만 캐시와 마찬가지로 CDN도 다음 사항을 고려해야 한다.

    • CDN은 보통 써드 파티가 운영하므로 데이터 전송양에 따라 요금이 발생한다. 따라서 자주 사용되지 않는 콘텐츠는 CDN에서 제외하여 비용을 절약해야 한다.
    • 적절한 만료 기간을 설정하여 콘텐츠의 신선도가 떨어지지 않도록 해야 한다.
    • CDN이 동작하지 않을 경우, 원본 서버로부터 정적 콘텐츠를 받아볼 수 있어야 한다.
    • 아직 만료되지 않은 콘텐츠여도 새로운 콘텐츠가 등장할 수 있다. 오브젝트 버저닝(ex. `image.png?v=2`)을 통해 다른 버전을 서비스해야 한다.

     

    stateless와 수평 확장

    HTTP는 stateless, 즉 상태 정보를 저장하지 않는다. 상태 정보를 저장하지 않으므로 요청마다 필요한 모든 값을 전달한다. 서버가 종료되었다 켜지는 경우에도 서버가 정상적으로 띄워지기만 하면 해당 요청은 정상적으로 처리될 수 있다.

     

    stateless는 수평 확장의 필수 조건이다. 웹 서버가 여러 개인 경우를 가정해보자. `A 서버`가 `C 사용자`의 상태 정보를 저장하고 있는 상황에서 `C 사용자`의 요청이 `B 서버`로 간다면 요청이 제대로 처리되지 않을 수 있다. 따라서 stateless를 통해 어느 웹 서버에서도 제대로 동작할 수 있어야 한다.

     

    데이터 센터

    데이터 센터는 컴퓨팅 시스템과 장비가 위치한 물리적 지역을 의미한다. 다중 데이터 센터를 이용하면 가용성을 높일 수 있다는 장점이 있다. 장애가 없는 상황에서 사용자 요청은 가장 가까운 데이터 센터로 라우팅된다. 하지만 데이터 센터 중 하나에 장애가 발생하면 장애가 없는 데이터 센터로 전송된다.

     

    이를 위해서는 다음 기술들이 필요하다.

    • 사용자에게 가장 가까운 데이터 센터로 트래픽을 보내야 한다.
    • 데이터 센터마다 별도의 DB를 사용하고 있고 하나의 센터에서 장애가 발생한 상황이라면, failover 할 수 있도록 데이터가 여러 데이터 센터에 걸쳐 다중화되어 있어야 한다.

     

    메시지 큐

    메시지 큐는 비동기로 메시지를 주고 받을 수 있도록 지원한다. 메시지 큐 아키텍처는 다음과 같이 구성되어 있다.

    • 생산자 (= publisher = producer) : 메시지를 메시지 큐에 발행한다
    • 구독자 (= subscriber = consumer) : 메시지큐에서 메시지를 받아 처리한다
    • 메시지 큐

    이처럼 메시지 큐를 이용하면 서비스 간 결합도를 낮추기 때문에 발신자와 수신자는 서로를 직접 알 필요가 없다. 또한, 각 부분을 독립적으로 개발하고 운영할 수 있어 확장성도 높다.

    💡 메시지 큐 종류에는 Kafka, RabbitMQ, JMS 등이 있다.

    '학습기록 > 독서' 카테고리의 다른 글

    [Good Code, Bad Code] 2장 추상화 계층  (0) 2024.02.01
    [Good Code, Bad Code] 1장 코드 품질  (1) 2024.01.24
    댓글