이 글은 책을 보고 배운 내용을 요약합니다. 자세한 설명은 생략되어 있기 때문에 책을 직접 구입해서 보시길 바랍니다.
사용자 수에 따른 규모 확장성
1장에서는 사용자가 많아짐에 따라 시스템을 어떻게 설계해야되는지, 그리고 어떤 지식이 필요한지에 대해서 소개한다.
단일 서버
모든 컴포넌트를 1개의 서버에서 실행할 때를 의미한다. 클라이언트가 요청을 보냈을 때, 서버로 어떻게 진입할 수 있는지 자세하게 설명해주지만 생략하도록 하겠다.
데이터베이스 분리(책 소제목은 데이터베이스)
사용자가 늘어나면 애플리케이션과 데이터베이스를 독립적으로 확장할 수 있게 하기 위해 두 서버를 나눠서 각각 운영한다. 이를 통해 트래픽 처리와 데이터베이스 조회 연산에 대한 리소스를 나눠서 처리할 수 있다. 여기서 규모가 더 커지려면 수직적 규모 확장(scale up
)과 수평적 규모 확장(scale out
)이라는 개념을 알아야 한다.
수직적 규모 확장 vs 수평적 규모 확장
수직적 규모 확장
수직적 규모 확장은 흔히 말하는 scale up
에 해당하는 말로 현재 가지고 있는 서버의 자원 자체를 늘리는 것이다. 예를 들어, CPU를 더 좋은 것을 쓰고 메모리를 추가하는 행위를 말한다. 단순하지만 치명적인 단점이 있다.
- 하나의 서버에서 CPU나 메모리를 무한대로 늘릴 수 있는 물리적인 방법이 없다.
- 장애에 대한 회복에 복구할 수 있는 방안이 없다.
수평적 규모 확장
수평적 규모 확장은 서버의 갯수를 늘리는 것이다. 흔히 scale out
이라고 부르는 개념으로 제약이 없기 때문에 확장성이 매우 뛰어나다.
여기까지는 시스템에 사용자 수가 늘어났을 때 어떻게 물리적인 서버를 구성할지에 대한 이야기였다. 이제부터는 수많은 요청들을 어떻게 처리할 수 있는지에 대해 설명한다.
로드 밸런서
너무 많은 요청이 서버로 들어오면 서버의 응답이 없거나 서버 자체가 죽을 수도 있다. 이를 해결하기 위해서는 요청을 분산할 필요가 있는데 이 역할을 로드밸런서가 해준다. 로드 밸런서는 공개 IP 주소로 들어온 요청에 대해서 사설 IP로 할당되어 있는 여러 개의 서버를 구성하여 각 서버에게 적절하게 요청을 전달한다. 여기서 재밌는 점은 외부에서는 이 사설 IP 주소를 모르고 아예 접근할 수도 없다. 같은 네트워크 안에 있어야 이 사설 IP를 사용할 수 있다. 이러한 특징을 이용해서 특정 서버가 죽는다면 다른 서버로 요청을 보내거나 너무 많은 요청이 들어온 경우에는 트래픽을 분산해서 전달할 수 있다.
웹 계층은 로드 밸런서를 통해서 부하를 분산할 수 있다는 사실을 알았다. 그렇다면 데이터베이스 계층은 어떨까?
데이터베이스 다중화
대부분의 DBMS는 다중화를 지원한다. 구조는 주로 마스터 - 슬레이브 구조로 되어 있다. 여기서 중요한 점은 마스터는 데이터베이스를 변경하는 명령어(insert, delete, update)등을 수행하고 각 슬레이브에 변경된 데이터를 전달한 다음 슬레이브에서 읽기(select) 명령어를 수행할 수 있게 해준다는 것이다. 다들 알다시피 대부분의 애플리케이션은 읽기 트래픽이 쓰기 트래픽보다 많기 때문에 읽기 트래픽을 해결하기 위해 이런 구조를 갖는다.
장애 상황에 대해서 생각해보자.
- 부 데이터베이스가 죽는 경우
- 부 데이터베이스가 한개면 일시적으로 주 데이터베이스가 읽기 연산을 가져가서 부하가 잠깐 많아지기는 하지만 서비스는 정상적으로 동작한다.
- 부 데이터베이스가 여러개면 하나가 죽는 것에 대해서 문제가 되지 않는다.
- 주 데이터베이스가 죽는 경우
- 부 데이터베이스 중 하나가 주 데이터베이스가 되어 읽기 연산을 처리하면 된다.
여기까지는 웹 계층과 데이터베이스 계층의 부하를 어떻게 분산하지는를 살펴봤다. 그렇다면 응답 시간을 개선하기 위해서는 어떻게 해야할까? 그 첫번째는 캐시를 사용하는 것이다.
캐시
캐시는 오래 걸리는 연산을 메모리에 저장하는 것이다. 애플리케이션의 연산은 대부분 데이터베이스를 얼마나 호출 하는지에 있다. 이를 해결하기 위해 캐시 계층을 두고 요청이 들어왔을 때 캐시 계층에 값이 있는지 확인하고 없으면 데이터베이스로부터 다시 가져오는 식으로 하는 것이 좋다. 캐시에 없는 경우에는 데이터베이스에 있는 값을 캐시에 저장해야한다.
캐시 서버를 사용할 때는 다음과 같은 주의사항이 있다.
- 데이터 갱신은 자주 일어나지 않지만 조회가 빈번할 때 사용한다.
- 캐시는 휘발성이기 때문에 영구적으로 저장할 필요성이 있는 것은 데이터베이스에 저장해야한다.
- 캐시의 보관 시간은 적절한 기간을 지정해야한다. 너무 짧으면 데이터베이스를 너무 자주 조회하고 너무 길면 원본과 데이터 동기화가 안된다.
- 일관성을 유지하기 위해 노력해야한다.
- 장애에 대비하여 캐시 서버를 항상 다수로 두어야 한다.
- 캐시 서버는 메모리를 과할당하는 것이 좋다.
- 캐시 서버에서 데이터를 방출하는 것은 LRU, LFU, FIFO 같은 정책을 사용하면 된다.
여기까지는 자체적으로 운영할 수 있는 캐시 서버에 대해서 이야기했다. 외부에서도 캐시를 할 수 있는데 대표적으로 CDN이 있다.
콘텐츠 전송 네트워크(CDN)
CDN은 정적 콘텐츠를 저장하는데 사용한다. 특징은 클라이언트로부터 지리적으로 가까운 CDN 서버로부터 컨텐츠를 가져가는 것이다. 일반적으로 CDN은 CDN 서비스 사업자에 돈을 주고 구매하여 사용한다. CDN이 동작하는 방식는 캐시가 동작하는 방식과 비슷함으로 자세한 내용을 알고 싶으면 책을 참고하기 바란다.
CDN을 사용할 때 다음과 같은 점을 주의해야한다.
- 전부다 CDN에 저장하면 돈이 많이 든다. 자주 사용하는 것만 CDN으로 등록하는 것이 좋다.
- 콘텐츠 갱신을 위한 주기를 적절하게 두어야 한다.
- CDN 서버 장애에 대해서 대처하기 위해서 방어를 해야한다.
- 콘텐츠 무효화 방법은 구상해야한다.
이로 인한 장점은 다음과 같다.
- 정적 콘텐츠의 응답시간이 더 빨라진다.
- 캐시로 인해 데이터베이스 부하가 줄어든다.
무상태(stateless) 웹 계층
무상태를 갖는다는 것은 사용자의 상태 정보(세션과 같은)를 특정 서버에 저장하지 않는다는 것이다. 왜냐하면 상태 정보를 특정 서버에만 저장하면 해당 서버에만 요청을 보내야하기 때문이다. 이를 해결하기 위해서는 공유 저장소를 가지면 된다.
여기까지는 특정 지역 또는 나라에서 서비스 하는 것에 대해서 살펴보았다. 만약 서비스가 전세계 어디에서나 운영되어야 한다면 어떻게 해야할까? 각 지역에 맞는 데이터 센터에 서버를 설치하면 된다.
데이터 센터
장애가 없는 상황이라면 사용자가 가장 가까운 데이터 센터로 요청이 간다. 장애가 났을 때에 대해서는 책 내용을 확인하길 바란다.
메시지 큐
시스템을 크게 확장하기 위해서는 각 컴포넌트가 독립적으로 확장할 수 있는 구조를 가져야한다. 이 때 핵심 전략 중 하나가 큐다. 메세지 큐의 특징은 비동기적으로 발행자가 만든 메시지를 소비자가 메시지를 받아 그에 맞는 일을 수행한다는 것이다. 발행자와 소비자간의 메시지 전송이 동기적이 아니어도 된다는 것이다.
로그, 메트릭 그리고 자동화
서비스가 커지면 모니터링할 수 있는 도구를 도입해서 서비스를 지속적으로 모니터링할 필요가 있다.
- 로그
- 로그를 단일 서비스로 모아주는 도구를 활용하여 편리하게 검색하고 조회할 수 있도록 구성하는 것이 좋다.
- 메트릭
- 메트릭을 통해 시스템의 현재 상태를 파악할 수 있다.
- 메트릭에 대한 정보는 다음과 같다.
- 호스트 단위 메트릭 : CPU, 메모리, 디스크 I/O
- 종합(aggregated) 메트릭 : 데이터베이스 계층의 성능, 캐시 계층의 성능
- 핵심 비즈니스 메트릭 : 일별 능동 사용자, 수익, 재방문 등
- 자동화
- 코드 검증, 빌드, 테스트 배포등을 자동화하면 개발자의 시간을 아낄 수 있다.
데이터베이스의 규모 확장
데이터베이스의 규모를 확장하는 것이 수직적 확장과 수평적 확장이 있다.
- 수직적 확장
- 웹서버를 수직적으로 확장하는 것과 비슷하게 생각하면 된다.
- 단점도 결국 같다.
- 수평적 확장
- 데이터베이스의 수평적 확장은 샤딩이라고 부른다.
- 대규모를 데이터베이스를 샤드라고 부르는 작은 단위로 분할하는 기술을 말한다.
- 각 샤드에 저장되는 데이터 사이에는 중복이 없다.
- 데이터는 샤딩키(파티션 키)에 따라 각 샤드에 저장된다.
- 샤딩키는 하나 이상의 컬럼으로 구성할 수 있다.
- 샤딩을 할 때 고려해야할 점은 다음과 같다.
- 재 샤딩 : 하나의 샤드에 데이터가 너무 많을 때 데이터를 균등하게 나눠야 한다. 이에 대한 해결법은 5장 안정 해시에서 다룬다.
- 유명인사 문제 : 특정 샤드에만 조회가 많을 경우를 말한다. 이 때 이 샤딩키를 핫스팟키라고 부르는데 핫스팟 키를 각 샤드에 나눠서 저장하거나 샤드를 더 잘게 쪼개야할 수도 있다.
- 조인과 비정규화 : 데이터베이스를 여러 샤드 서버로 쪼개면 샤드에 걸친 데이터는 조인하기 어렵다. 이런 경우에는 데이터를 비정규화하여 질의를 해결할 수 있게 한다.
백만 사용자, 그리고 그 이상
수백만 사용자가 사용할 수 있는 서비스를 만들기 위해서는 지속적으로 시스템을 가다듬어야 한다. 1장을 내용을 요약하면 다음과 같다.
- 웹 계층은 무상태 계층으로
- 모든 계층에 다중화 도입
- 가능한 한 많은 데이터를 캐시할 것
- 여러 데이터 센터를 지원할 것
- 정적 콘텐츠는 CDN을 통해 서비스할 것
- 데이터 계층은 샤딩을 통해 그 규모를 확장할 것
- 각 계층은 독립적 서비스로 분할할 것
- 시스템을 지속적으로 모니터링하고 자동화 도구들을 활용할 것
Uploaded by Notion2Tistory v1.1.0