1. Scalability
- 분산시스템에서 확장성이란 사용자 수나 데이터 양이 증가해도 시스템이 처리할 수 있는 능력을 말합니다.
- 한 명의 사용자를 지원하는 시스템에서 시작해서 몇백만 사용자를 지원하는 시스템을 설계하는 방법을 알아보며 확장성에 대해 알아봅니다.
1.1 시스템 규모 확장 핵심 전략
- 시스템의 확장성을 확보하기 위한 핵심 전략은 다음과 같습니다.
- 웹 계층은 무상태 계층으로 설계
- 모든 계층에 다중화 도입
- 가능한 많은 데이터를 캐시
- 여러 데이터 센터 지원
- 정적 콘텐츠는 CDN을 통해 서비스
- 데이터 계층은 샤딩을 통해 규모 확장
- 각 계층은 독립적 서비스로 분할
- 시스템을 지속적으로 모니터링하고 자동화 도구 활용
확장성의 중요성
대규모 서비스에서는 단일 서버로 모든 트래픽을 처리할 수 없습니다. 시스템의 확장성을 고려한 설계가 필수적입니다.
2. 규모 확장 방식
2.1 Scale Up (수직적 확장)
- 기존 서버나 장비의 성능을 높여 처리 능력을 향상시키는 방법입니다.
- CPU, 메모리, 인스턴스 유형 업그레이드 등을 통해 처리 능력을 향상시킵니다.
- 수직 확장은 단일 노드 성능을 개선하여 작업량이나 요구 사항이 증가하더라도 정상적으로 이를 처리하는 데 중점을 둡니다.
장점
- 단순성
- 기존 시스템 아키텍처나 소프트웨어에 최소한의 변경만 필요합니다.
- 서버로 유입되는 트래픽의 양이 적을 때 좋은 선택입니다.
- 적은 작업량의 경우 여러 노드 대신 단일 노드에서 충분히 처리가 가능하며 비용 면에서 더 효율적일 수 있습니다.
단점
- 수직적 규모 확장에는 한계가 존재합니다.
- 한 대의 서버에 CPU와 메모리를 무한대로 증설할 방법은 없습니다.
- 자동복구 방안이나 다중화 방안을 제시하지 않습니다.
- 서버에 장애가 발생하면 모든 서비스가 완전히 중단 (SPOF 위험성)
- 고성능 서버로 갈수록 가격이 기하급수적으로 상승합니다.
Scale Up의 한계
대규모 서비스에서는 Scale Up의 단점으로 인해 주요 확장 전략으로 사용하지 않습니다. 하드웨어의 물리적 한계와 SPOF 위험성이 큽니다.
2.2 Scale Out (수평적 확장)
- 서버나 장비를 여러 대 추가하여 시스템의 처리 능력을 향상시키는 방법입니다.
- 인스턴스 수를 증가시켜 수평적 확장을 가능하게 합니다.
- 수평 확장은 여러 노드에 작업을 분산시켜 처리 능력을 향상시키는데 중점을 둡니다.
장점
- 여러 개의 서버를 두어 한 서버에 장애가 발생해도 전체 서비스가 중단되지 않습니다.
- SPOF 위험성이 낮습니다.
- 트래픽 증가에 따라 유연하게 서버 추가 가능합니다.
단점
- 분산 조정
- 여러 노드에 작업을 분산하려면 각 노드가 적절하게 협력하고 동기화할 수 있는 메커니즘이 필요합니다.
- 예를 들어 하나의 노드가 재고 수량을 더하거나 빼는 작업을 할 때 다른 노드도 동시에 이 정보를 공유해야 재고 수량이 일관되게 유지됩니다.
- 데이터 일관성
- 데이터가 여러 노드에 걸쳐 분산되므로 일관성을 유지하는 것이 더 어려워집니다.
- 이를 해결하려면 분산 트랜잭션이나 최종 일관성 같은 기법을 사용해야 합니다.
- Scale Up보다 구현하기 복잡합니다.
- 세션 관리 등 추가 고려사항이 존재합니다.
2.3 함께 사용하기
- Scale Up과 Scale Out 중 반드시 하나만 사용해야 하는 것은 아닙니다.
- 때에 따라서는 두 가지 방법을 함께 사용하여 시스템의 확장성을 확보할 수 있습니다.
3. 웹 계층 확장
3.1 로드밸런서
웹 계층의 수평적 규모 확장을 위해 로드밸런서를 사용합니다.
역할
- 부하 분산 집합에 속한 웹 서버들에게 트래픽을 고르게 분산
- 클라이언트는 로드밸런서를 통해 간접적으로 웹 서버에 접속
- 서버 간 통신에는 사설 IP 주소를 사용하여 보안 강화
가용성 향상
- 부하 분산 집합에 웹 서버를 추가하면 가용성 향상
- 서버 하나가 다운되면 모든 트래픽은 다른 서버로 전송되어 전체 서비스 중단 방지
부하 분산
- 트래픽 증가에 따라 새로운 서버를 부하 분산 집합에 추가 가능
- 로드밸런서가 자동으로 트래픽을 분산하여 각 서버의 부하 균등화
로드밸런서의 이점
로드밸런서를 도입하면 가용성과 확장성을 동시에 확보할 수 있습니다. 서버 장애 시 자동으로 트래픽을 다른 서버로 전환하고, 필요에 따라 서버를 추가하여 처리 용량을 늘릴 수 있습니다.
3.2 Stateless vs Stateful 아키텍처
- 웹 계층을 수평적으로 확장하기 위해서는 상태 관리 전략이 중요합니다.
Stateless 웹 계층 (무상태)
- 상태 정보(사용자 세션 데이터 등)를 웹 계층에서 제거하고, 관계형 데이터베이스나 NoSQL 같은 지속성 저장소에 보관하는 방식입니다.
- 장점
- 사용자 요청을 어떤 웹 서버로도 전달 가능
- 필요시 공유 저장소에서 상태 정보를 조회
- 서버 추가/제거가 자유로움
- 로드밸런싱이 단순하고 효율적
Stateful 웹 계층 (상태 유지)
- 서버가 클라이언트의 정보(상태)를 유지하여 요청들 사이에 공유하는 방식입니다.
- 단점
- 같은 클라이언트의 요청은 항상 같은 서버로 전송되어야 함
- 고정 세션(Sticky Session)이 필요하여 로드밸런서에 부담
- 서버 추가/제거가 복잡
- 서버 장애 시 해당 서버의 세션 정보 손실
Stateful의 문제점
Stateful 아키텍처는 확장성에 제약이 있습니다. 대규모 서비스에서는 Stateless 아키텍처를 채택하여 수평적 확장을 용이하게 하는 것이 바람직합니다.
4. 데이터 계층 확장
4.1 데이터베이스 다중화
- 웹 계층의 다중화는 로드밸런서를 통해 구현할 수 있습니다.
- 데이터베이스 다중화는 Master-Slave 구조를 통해 구현합니다.
- Master-Slave 구조
- 많은 DBMS는 다중화를 지원하며, 서버 사이에 Master와 Slave 관계를 설정합니다.
- Master (주 데이터베이스): 데이터 원본을 저장하며 쓰기 연산을 담당
- Slave (부 데이터베이스): Master로부터 사본을 전달받아 읽기 연산을 담당
- 대부분의 애플리케이션은 읽기 연산의 비중이 쓰기 연산보다 훨씬 높기 때문에, Slave 데이터베이스의 수가 Master보다 많습니다.
역할 분담
- Master:
- 쓰기 연산(INSERT, UPDATE, DELETE)을 처리
- 데이터 변경 사항을 Slave에 복제
- Slave:
- 읽기 연산(SELECT)을 처리
- Master로부터 데이터 사본을 전달받아 동기화
장점
- 성능 향상: 읽기와 쓰기 연산이 분리되어 병렬 처리 가능
- 데이터 보존: 자연 재해 등으로 일부 서버가 파괴되어도 데이터 보존
- 가용성 확보: 하나의 서버에 장애가 발생해도 다른 서버에서 서비스 지속
- 장애 대응
- Slave 한 대만 있는데 다운된 경우: 읽기 연산을 한시적으로 Master로 전달
- 여러 Slave 중 하나가 다운된 경우: 다른 Slave로 읽기 연산 분산
- Master가 다운된 경우: 한 대의 Slave를 새로운 Master로 승격하고, 추가 Slave 구성
읽기와 쓰기의 비율
대부분의 웹 애플리케이션에서 읽기 연산은 쓰기 연산보다 훨씬 많습니다. 이러한 특성을 고려하여 Slave를 여러 대 구성하면 읽기 성능을 크게 향상시킬 수 있습니다.
4.2 데이터베이스 샤딩
- 데이터베이스의 수평적 확장은 샤딩(Sharding)을 통해 구현합니다.
- 샤딩이란?
- 대규모 데이터베이스를 샤드(Shard)라는 작은 단위로 분할하는 기술
- 모든 샤드는 같은 스키마를 사용하지만, 샤드에 보관된 데이터 사이에는 중복이 없음
- 각 샤드는 독립적인 데이터베이스로 동작
- 예시
- 사용자 ID를 기준으로 샤딩하는 경우:
- 샤드 1: 사용자 ID 0-999
- 샤드 2: 사용자 ID 1000-1999
- 샤드 3: 사용자 ID 2000-2999
- 장점
- 데이터를 여러 서버에 분산하여 저장 용량 증가
- 쿼리 부하를 여러 서버에 분산하여 성능 향상
- 데이터베이스 서버 추가로 수평적 확장 가능
- 자세한 내용은 데이터베이스 샤딩 문서를 참고하시기 바랍니다.
샤딩과 복제의 조합
실제 운영 환경에서는 샤딩과 Master-Slave 복제를 함께 사용합니다. 각 샤드마다 Master-Slave 구조를 구성하여 가용성과 확장성을 동시에 확보할 수 있습니다.
5. 성능 최적화
5.1 캐시
- 웹 계층과 데이터 계층의 다중화를 통해 가용성과 확장성을 확보했습니다.
- 이제 응답 시간을 개선해야 합니다.
- 캐시의 역할
- 자주 조회되는 데이터를 메모리에 저장
- 데이터베이스 부하 감소
- 응답 시간 대폭 단축
- 캐시 전략과 구현 방법에 대한 자세한 내용은 별도 문서를 참고하시기 바랍니다.
- 자세한 내용은 캐시 문서를 참고하시기 바랍니다.
5.2 CDN (Content Delivery Network)
- 정적 콘텐츠(이미지, CSS, JavaScript 등)를 CDN으로 옮기면 응답 시간을 크게 개선할 수 있습니다.
- CDN의 장점
- 지리적으로 분산된 서버에서 콘텐츠 제공
- 사용자와 가까운 서버에서 콘텐츠 전송
- 원본 서버의 부하 감소