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

bw1611·2024년 1월 20일

단일 서버

1, 사용자는 도메인 이름을 이용하여 웹사이트에 접속한다. 이 접속을 위해서는 도메인 이름을 도메인 이름 서비스에 질의하여 IP 주소로 변환하는 과정이 필요하다.
2, DNS 조회로 웹 서버의 IP 주소가 반환된다.
3, 해당 IP 주소로 HTTP 요청이 전달된다.
4, 요청을 받은 웹 서버는 HTML 페이지나 JSON 형태의 응답을 반환한다.

DB

사용자가 많아지면 서버 하나로 충분하지 않아서 서버를 여러개 두는 생각을 해야한다.

- RDBMS

MySql, orcle, PostgreSQL 등을 RDBMS라고 부른다. 자료를 테이블과 열, 컬럼으로 표현하고, SQL을 사용하여 여러 테이블에 있는 데이터를 그 관계에 따라 JOIN 할 수 있다.

- NoSQL

DynamoDB, redis, MongoDB, Neo4j 등이 있으며 4 분류로 나눌 수 있다. key-value 저장소, 그래프 저장소, 컬럼 저장소, 문서 저장소가 있다. 비-관계형 DB는 일반적으로 JOIN을 지원하지는 않는다.

NoSQL을 고려해야할 경우

  • 아주 낮은 응답 지연시간
  • 데이터가 비정형
  • 데이터를 직렬화하거나 역직렬화 할 수 있기만 하면 됨
  • 아주 많은 양의 데이터를 저장할 필요가 있음

Scale-up vs Scale-out

- Scale-up

서버에 고사양 자원을 추가하는 행위이다. 하지만 Scale-up 확장에는 한계가 존재한다. 한 대의 서버에 CPU, 메모리를 무한대로 증성할 수 없고, 비용 또한 비싸다. 또한 장애에 대한 자동복구 방안이나 다중화 방안을 제시하지 않는다. (서버 장애시 웹페이지 완전 중단)

위의 문제를 해결하기 위하여 로드밸런서를 도입할 수 있다.

- 로드밸런서

사용자는 로드밸런서의 Public IP로 접속한다. 서버 간 통신에는 Private IP가 이용되며, 위처럼 스케일 아웃을 통해서 서버를 여러 대로 늘리게 되면 장애를 자동복구하지 못하는 문제도 해소할 수 있고, 웹 계층의 가용성은 향상된다.

- DB 다중화

많은 데이터베이스에서 다중화를 지원한다. 보통은 서버 사이에 master - slave 관계를 설정하고 데이터 원본은 master 서버에, 사본은 slave 서버에 저장하는 방식이다.
쓰기 연산은 master에서만 지원하고 slave DB는 사본을 전달받고 읽기 연산만 지원한다.

DB 다중화의 장점

  • 더 나은 성능 : 변경에 관한 연산은 master DB에서 처리하고 읽기 연산은 slave 서버에서 처리 된다. 병렬로 처리될 수 있는 질의의 수가 늘어나므로, 성능이 좋아진다.
  • 안전성 : DB 서버에 문제가 생기더라도 데이터가 보존될 수 있다.
  • 가용성 : 하나의 데이터베이스에서 장애가 발생하더라도 다른 서버에 있는 데이터를 가져와서 게속 서비스가 가능

DB 다중화와 로드밸런서를 적용한 모습이다.

캐시

값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고, 뒤이은 요청이 보다 빨리 처리될 수 있도록 하는 저장소다.

캐시 계층

데이터가 잠시 보관되는 곳으로 DB보다 횔씬 빠르다. 또한 데이터베이스의 부하도 줄일 수 있으며 규모를 독립적으로 확장시키는 것도 가능해진다.

위의 사진은 읽기 주도형 캐시 전략이라고 부른다. 이렇게 사용하는 것 이외에도 캐시 전략이 있는데, 캐시할 데이터 종류, 크기, 액세스 패턴에 맞는 캐시 전략을 선택하면 된다.

캐시 사용시 유의할 점

  • 캐시는 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어난다면 고려해볼만 하다.
  • 영속적으로 보관할 데이터를 캐시에 두는 것은 바람직하지 않다.
  • 캐시는 데이터를 휘발성 메모리에 두기 때문에, 캐시 서버가 재시작되면 모든 데이터는 사라진다.
  • 만료된 데이터는 캐시에서 삭제되어야 한다.
  • 만료 기한에 대한 정책을 마련하는 것이 좋다.
  • 만료 기한이 너무 짧으면, 데이터베이스를 너무 자주 읽게 되며, 너무 길면 원본과 차이가 날 가능성이 높아진다.
  • 데이터 저장소의 원본과 캐시 내의 사본 일관성을 확인해야 한다.
  • 캐시 서버를 한 대만 두는 경우 해당 서버는 단일 장애 지점(SPOF)이 되어 버릴 수 있다.
  • 캐시 메모리 크기는 너무 크지도 작지도 않게 적절하게 잡아야 한다.
  • 캐시가 꽉 차버리면 LRU, LFU, FIFO 같은 정책들을 사용해서 사용해야 한다.

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

CDN은 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크이다. 이미지, 비디오, CSS, JavaScript 파일 등을 캐시할 수 있다. 요청 경로, 질의 문자열, 쿠키, 요청 헤더 등의 정보에 기반하여 HTML 페이지를 캐시할 수 있다.

CDN 사용 시 고려해야 할 사항

  • 비용 : CDN으로 들어가고 나가는 데이터 전송 양에 따라 요금을 내므로 자주 사용되지 않는 콘텐츠를 캐싱하는 것은 이득이 크지 않다.
  • 적절한 만료 시한 설정 : 시의성이 중요한 콘텐츠의 경우 만료 시점을 잘 정해야 한다.
  • CDN 장애에 대한 대처 방안 : CDN 자체가 죽었을 경우 웹사이트/애플리케이션이 어떻게 동작해야 하는지 고려해야 한다.

  • 정적 콘텐츠는 더 이상 웹 서버를 통해 서비스하지 않으며, CDN을 통해 제공하여 더 나은 성능을 보장한다.
  • 캐시가 데이터베이스 부하를 줄여준다.

무상태 웹 계층

웹 계층을 수평적으로 확장하는 방법을 고려해보자. 이를 위해서는 상태 정보(사용자 세션 데이터와 같은 정보)를 웹 계층에서 제거해야 한다. 바람직한 전력은 상태 정보를 관계형 DB나 NoSQL 같은 지속성 저장소에 보관하고, 필요할 때 가져오도록하는 방법이다.

- 상태 정보 의존적인 아키텍처

상태 정보를 보관하는 서버는 클라이언트 정보, 즉 상태를 유지하여 요청들 사이에 공유되도 하지만, 무상태 서버에는 이런 장치가 없다.

위의 그림에서는 사용자 A는 서버1에서만 인증이 가능하기 때문에 이런 문제를 해결하기위에 대부분 로드밸런서가 이를 지원하는 고정 세션이라는 기능을 제공한다. 하지만 이는 로드밸런서에 부담을 주며, 로드밸런스 뒷단에 서버를 추가하거나 제거하기도 까다로워진다.

- 무상태 아키텍처

이러한 구조에서는 사용자로부터 HTTP 요청은 어떤 웹 서버로도 전달될 수 있다. 웹 서버는 상태 정보가 필요한 경우 공유 저장소로부터 데이터를 가져온다. 따라서 상태 정보는 웹 서버로부터 물리적으로 분리되어 있다.

이러한 공유 저장소는 Redis와 같은 캐시 시스템일 수도 있으며, NoSQL일 수도 있다.

데이터 센터

위의 그림은 데이터 센터를 2개 이용하는 사례이다. 장애가 없는 상황에서는 사용자는 가까운 데이터 센터로 안내된다. 이 절차를 지리적 라우팅이라고 부른다. 지리적 라우팅에서의 geoDNS는 사용자의 위치에 따라 도메인 이름을 어떤 IP 주소로 변환할지 결정할 수 있도록 해주는 DNS 서비스이다.

메시지 큐

메시지 큐는 메시지의 무손실을 보장하는, 비동기 통신을 지원하는 컴포넌트다. 메시지 큐에는 보통 소비자 혹은 구독자라 불리는 서비스 혹은 서버가 연결되어 있으며, 메시지에 받아 그에 맞는 동작을 수행하는 역할을 한다.

메시지 큐를 이용하면 서비스 또는 서버 간 결합이 느슨해지며, 규모 확장성이 보장되어야 하는 안정적 애플리케이션을 구성하기 좋다.

로그, 메트릭 그리고 자동화

로그, 메트릭, 자동화는 소규모의 사이트에서는 추천되지 않지만 웹 사이트의 사업 규모가 커지고 나면, 필수적으로 투자해야하는 부분이다.

데이터베이스의 규모 확장

저장할 데이터가 많아지면 데이터베이스에 대한 부하도 증가한다. 데이터베이스의 규모 확장에는 두가지 접근법이 존재한다.

- Scale up

수직적 규모 확장법은 기존 서버에 더 많은, 또는 고성능의 자원을 증설하는 방법이다.

  • 단점

1, 데이터베이스 서버 하드웨어에는 한계가 있으므로 CPU, RAM 등을 무한 증설할 수 없다.
2, SPOF로 인한 위험성이 크다.
3, 비용이 비싸다.

- Scale out

데이터베이스의 수평적 확장은 샤딩이라고도 부르는데, 더 많은 서버를 추가함으로써 성능을 향상시킬 수 있도록 한다. (샤드는 작은 단위로 분활하는 기술을 말한다.)

모든 샤드는 같은 스키마를 쓰지만 샤드에 보관되는 데이터 사이에는 중복이 없다.

샤딩 전략을 구현할 때 고려해야 할 가장 중요한 것은 샤딩 키를 어떻게 정하느냐 하는 것이다. 샤딩 키를 올바른 데이터베이스에 질의를 보내어 데이터 조회나 변경을 처리하므로 효율을 높일 수 있기 때문이다.

  • 샤딩을 도입하였을 경우 신경써야 할 문제

1, 데이터의 재 샤딩
데이터가 너무 많아져서 하나의 샤드로는 더 이상 감당하기 어려울 때
샤드 간 데이터 분포가 균등하지 못하여 어떤 샤드에 할당된 공간 소모가 다른 샤드에 비해 빨리 진행될 때
2, 유명 인사: 핫스팟 키 문제라고도 부르는데, 특정 샤드에 쿼리가 집중되어 서버에 과부하가 걸리는 문제
3, 조인과 비정규화
일단 하나의 데이터베이스를 여러 샤드 서버로 쪼개고 나면, 여러 샤드에 걸친 데이터를 조인하기가 힘들어진다. 이를 해결하는 한 가지 방법은 데이터베이스를 비정규화하여 하나의 테이블에서 쿼리가 수행될 수 있도록 하는 것이다.

profile
Java BackEnd Developer

0개의 댓글