본문 바로가기

가상 면접 사례로 배우는 대규모 시스템 설계 기초

[가상 면접 사례로 배우는 대규모 시스템 설계 기초] 1장 사용자 수에 따른 규모 확장성 - 수직적 규모 확장 vs 수평적 규모 확장

 

1) 서문

- 소위 스케일 업(scale up)이라고도 하는 수직적 규모 확장(vertical scaling) 프로세스는 서버에 고사양 자원(더 좋은 CPU, 더 많은 RAM 등)을 추가하는 행위를 말한다. 반면, '스케일 아웃(scale out)'이라고도 하는 수평적 규모 확장 프로세스는 

  더 많은 서버를 추가하여 성능을 개선하는 행위를 말한다. 

 

- 서버로 유입되는 트래픽의 양이 적을 때는 수직적 확장이 좋은 선택이며, 이 방법의 가장 큰 장점은 단순함이다.

  그러나 불행하게도 이 방법에는 몇 가지 심각한 단점이 있다.

 

(1) 수직적 규모 확장에는 한계가 있다. 한 대의 서버에 CPU나 메모리를 무한대로 증설할 방법은 없다

(2) 수직적 규모 확장법은 장애에 대한 자동복구(failover) 방안이나 다중화(redundancy) 방안을 제시하지 않는다.

      서버에 장애가 발생하면 웹사이트/앱은 완전히 중단된다. 

 

-이런 단점 때문에, 대규모 애플리케이션을 지원하는 데는 수평적 규모 확장법이 보다 적절하다.

 앞서 본 설계에서 사용자는 웹 사이트에 접속할 수 없다. 또한, 너무 많은 사용자가 접속하여

 웹 서버가 한계 상황에 도달하게 되면 응답 속도가 느려지거나 서버 접속이 불가능해질 수도 있다.

 이런 문제를 해결하는 데는 부하 분산기 또는 로드밸런스(load balancer)를 도입하는 것이 최선이다.

 

 

2) 로드밸런서

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

  그림 1-4는 로드밸런서가 어떻게 동작하는지 보여주고 있다. 

 

 

- 그림 1-4와 같이 사용자는 로드밸런서의 공개 IP 주소(public IP address)로 접속한다.

   따라서 웹 서버는 클라이언트의 접속을 직접 처리하지 않는다.

   더 나은 보안을 위해, 서버 간 통신에는 사설 IP 주소(private IP address)가 이용된다.

   사설 IP 주소는 같은 네트워크에 속한 서버 사이의 통신에만 쓰일 수 있는 IP 주소로,

   인터넷을 통해서는 접속할 수 없다.

   로드밸런서는 웹 서버와 통신하기 위해 바로 이 사설 주소를 이용한다. 

 

- 그림 1-4에 나온대로, 부하 분산 집합에 또 하나의 웹 서버를 추가하고 나면 

   장애를 자동복구하지 못하는 문제(no failover)는 해소되며,

   웹 계층의 가용성(availability)은 향상된다.

   좀 더 구체적으로 살펴보면 다음과 같다. 

   

(1) 서버 1이 다운되면(offline) 모든 트래픽은 서버 2로 전송된다. 따라서 웹 사이트 전체가 다운되는 일이

      방지된다. 부하를 나누기 위해 새로운 서버를 추가할 수도 있다.

 

(2) 웹사이트로 유입되는 트래픽이 가파르게 증가하면 두 대의 서버로 트래픽을 감당할 수 없는 시점이 오는데,

      로드밸런서가 있으므로 우아하게 대처할 수 있다.

      웹 서버 계층에 더 많은 서버를 추가하기만 하면 된다. 그러면 로드밸런서가 자동적으로 트래픽을

      분산하기 시작할 것이다. 

 

- 이제 웹 계층은 괜찮아 보이는데, 그렇다면 데이터 계층은 어떤가? 현재 설계안에는 하나의 데이터베이스

  서버 뿐이고, 역시 장애의 자동복구나 다중화를 지원하는 구성은 아니다.

  데이터베이스 다중화는 이런 문제를 해결하는 보편적인 기술이다. 한 번 살펴보자. 

 

 

3) 데이터베이스 다중화

- 위키피디아에 따르면, "많은 데이터베이스 관리 시스템이 다중화를 지원한다.

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

  사본은 부 서버에 저장하는 방식이다.

  쓰기 연산(write operation)은 마스터에서만 지원한다. 부 데이터베이스는 주 데이터베이스로부터 그 사본을 전달받으며,

  읽기 연산(read operation)만을 지원한다. 데이터베이스를 변경하는 명령어들, 가령 insert, delete, update 등은 

  주 데이터베이스로만 전달되어야 한다. 

 

- 대부분의 애플리케이션은 읽기 연산의 비중이 쓰기 연산보다 훨씬 높다.

  따라서 통산 부 데이터베이스의 수가 주 데이터베이스의 수보다 많다.

  그림 1-5는 이 구성을 보여주고 있다. 

 

- 데이터베이스를 다중화하면 다음과 같은 이득이 있다. 

 

(1) 더 나은 성능

- 주-부 다중화 모델에서 모든 데이터 변경 연산은 주 데이터베이스 서버로만 전달되는 반면

  읽기 연산은 부 데이터베이스 서버들로 분산된다.

  병렬로 처리될 수 있는 질의(query)의 수가 늘어나므로, 성능이 좋아진다. 

 

(2) 안정성(reliability)

- 자연 재해 등의 이유로 데이터베이스 서버 가운데 일부가 파괴되어도 데이터는 보존될 것이다.

  데이터를 지역적으로 떨어진 여러 장소에 다중화시켜 놓을 수 있기 때문이다. 

 

(3) 가용성(availability)

- 데이터를 여러 지역에 복제해 둠으로써, 하나의 데이터베이스 서버에 장애가 발생하더라도

  다른 서버에 있는 데이터를 가져와 계속 서비스할 수 있게 된다. 

 

- 앞 절에서 우리는 로드밸런서가 시스템 가용성을 어떻게 높이는지 살펴보았다.

  데이터베이스에 대해서도 같은 질문을 던져보자. 

  데이터베이스 서버 가운데 하나가 다운되면 무슨 일이 벌어지는가?

  그림 1-5에 제시한 설계는 이런 상황을 감당할 수 있다. 

 

- 부 서버가 한 대뿐인데, 다운된 경우라면, 읽기 연산은 한시적으로 모두 주 데이터베이스로 전달될

  것이다. 또한 즉시 새로운 부 데이터베이스 서버가 장애 서버를 대체할 것이다. 

  부 서버가 여러 대인 경우에 읽기 연산은 나머지 부 데이터베이스 서버들로 분산될 것이며,

  새로운 부 데이터베이스 서버가 장애 서버를 대체할 것이다. 

 

- 주 데이터베이스 서버가 다운되면, 한 대의 부 데이터베이스만 있는 경우 

  해당 부 데이터베이스 서버가 새로운 주 서버가 될 것이며, 모든 데이터베이스 연산은

  일시적으로 새로운 주 서버상에서 수행될 것이다.

  그리고 새로운 부 서버가 추가될 것이다.

  프로덕션(production) 환경에서 벌어지는 일은 이것보다는 사실 더 복잡한데,

  부 서버에 보관된 데이터가 최신 상태가 아닐 수 있기 때문이다. 

  없는 데이터는 복구 스크립트(recovery script)를 돌려서 추가해야 한다. 

 

- 다중 마스터(multi-masters)나 원형 다중화(circular replication) 방식을 도입하면

  이런 상황에 대처하는 데 도움이 될 수도 있지만 해당 구성은 훨씬 복잡하며

  그에 대한 논의는 이 책에서 다룰 수 있는 내용의 범위를 넘어선다.

  관심 있는 독자들은 참고문헌을 살펴보기 바란다.

 

- 그림 1-6은 로드밸런서와 데이터베이스 다중화를 고려한 설계안이다. 

 

  - 이 설계안은 다음과 같이 동작한다.

(1) 사용자는 DNS로부터 로드밸런서의 공개 IP 주소를 받는다

(2) 사용자는 해당 IP 주소를 사용해 로드밸런서에 접속한다

(3) HTTP 요청은 서버 1이나 서버 2로 전달된다

(4) 웹 서버는 사용자의 데이터를 부 데이터베이스 서버에서 읽는다

(5) 웹 서버는 데이터 변경 연산은 주 데이터베이스로 전달한다. 

     데이터 추가, 삭제, 갱신 연산 등이 이에 해당한다. 

 

- 이제 웹 계층과 데이터 계층에 대해 충분히 이해하게 되었으니, 

   응답 시간(latency)을 개선해 볼 순서다. 응답 시간은 캐시(cache)를 붙이고, 

   정적 컨텐츠를 컨텐츠 전송 네트워크(Content Delivery Network, CDN)로 옮기면 계선할 수 있다.