저번 글에 이어서, 많은 요청이 발생했을때 데이터베이스를 어떻게 설계해야 하는지 알아보도록 하자.
데이터베이스 다중화
대부분의 데이터베이스는 다중화 기능을 제공한다. 예를들어 AWS에서는 Read Replica를 통해 Master-Slave 관계를 만들 수 있다. 즉, 같은 데이터베이스를 하나의 Master DB와 여러개의 SlaveDB로 두는 방식으로, 원본이 Master서버에 사본이 Slave서버에 저장된다.
이경우 Master DB에서는 Write(쓰기연산)가 가능하고, Slave DB에서는 Read(읽기연산)만 가능하다. 웹이나 앱등을 구현하다보면, 쓰기/수정/삭제연산과 같이 Write연산보다는 읽기연산인 Read가 훨씬 많이 사용하게 되는것을 알게된다. 사실 당연하다. 뭔가를 수정,삭제하기 위해서 우선 해당 정보를 읽어야 되니까! 아무튼 대부분 어플리케이션에서 쓰기보다는 읽기 연산이 빈번하기 때문에, Master-Slave 기법이 효과적이다.

1. Master-Slave 모델에서 모든 데이터 Write작업은 Master로, Read작업은 Slave서버로 분산한다. 병렬로 처리될 수 있는 쿼리의 수가 늘어나므로 성능상의 이점이 있다.
2. 데이터베이스 서버가 일부 파괴되더라도 다중화를 통해 복구가 가능하다. 즉, 안정성과 가용성을 챙길 수 있다.
(CF) 참고로 Master DB에서도 Read(조회연산)가 가능하다. 다만 Master DB에 Write(쓰기연산)을 하게 되면, 해당 작업이 Slave(Read Replica라고도 한다)에 전달되며 자동 동기화된다. 따라서 데이터가 전달되는 시간동안 약간의 데이터 정합성이 깨지는 Replica Lag이 발생하는데, AWS에서는 이 시간이 일반적으로 0.1초 이내라고 말하고 있다. 따라서 일반적으로는 Read Replica를 사용하면 괜찮고, 시간에 민감한 데이터에 대해서만 Master DB에서 조회하면 된다.
DB서버 하나에 장애가 발생했을때의 복구방안
그렇다면 데이터베이스 서버 한대에 장애가 발생했을때, 어떤식으로 복구되는지 알아보자.
이러한 문제상황은 다음과같이 분리해서 생각해 볼 수 있다.
1. Slave DB가 한대인데 장애가 났을 경우
읽기연산은 한시적으로 MasterDB로 전달된다. 그리고 즉시 새로운 SlaveDB가 장애서버를 대체한다.
2. Slave DB가 여러대인데 한대에 장애가 났을 경우
읽기연산은 나머지 Slave서버로 분산되어 요청되고, 새로운 SlaveDB가 장애서버를 대체한다.
3. Master DB가 다운되고, 한대의 Slave DB만 남은경우
Slave DB가 새로운 Master DB로 승격되고, 모든 DB연산은 일시적으로 새로운 Master DB위에서 수행된다. 그리고 새로운 SlaveDB가 추가된다.
만약 Slave DB가 Master DB를 대체하게 되는 경우, Replica Lag에 의해 현재 데이터 상태가 최신상태가 아닐 수 있다. 따라서 이때는 복구스크립트를 실행해서 데이터를 보완해야한다. 다중Master나 원형 다중화 방식을 도입해 대처할 수 있다고 한다.

1. 사용자는 DNS로부터 로드밸런서 공개IP주소를 받는다.
2. 사용자는 해당 IP주소를 사용해 로드밸런서에 요청을 보낸다.
3. HTTP요청은 서버1 or 서버2로 전달된다.
4-1. 요청이 읽기연산일 경우, 웹서버는 Slave DB에서 데이터를 읽는다.
4-2. 요청이 쓰기연산을 경우, 웹서버는 Master DB에서 create, delete, update 연산 등을 수행한다.
이렇게 서버에서와 DB에서 대규모 요청을 처리하는 방법을 알아보았다.
이제부터는 이러한 설계를 더욱 빠르고, 효율적으로 사용하기 위한 기법인 캐싱, CDN 등을 알아보자!
캐시
그간 프로젝트를 진행하면서, 같은 결과를 위해 반복적으로 요청되는 비효율적 API들이 있었다. 예를들어 커뮤니티에 접속했을때 모든 사용자에게 보여줄 "인기 게시물 조회 API"가 있다. 유저가 누군지와도 상관없고, 일정기간동안 결과도 변하지 않는 데이터다. 즉, 매번 계산할 필요없이, 한번만 계산해서 응답해도 되는 데이터다. 이걸 매번 계산할경우... 느리고 자원낭비일것이다.
따라서 이러한 문제를 해결하기 위해 "미리 계산해서 저장해두는 방법"을 떠올릴 수 있고, 이게 바로 캐시인것이다.
그렇다면 캐시는 어떻게 빠를까?
데이터베이스는 기본적으로 Disk 기반이다. 그래서 읽고 쓰는 연산이 느리다.
반면, 캐시는 메모리 기반으로 동작하기 때문에 데이터베이스보다 훨씬 빠르다.
그렇기 때문에 DB앞에 메모리 기반의 캐시를 두고, 값비싼 연산이나 자주 참조되는 데이터를 저장해둠으로써 반복되는 요청에 대해 DB단까지 갈 필요없이 빠르게 처리한다(이를 cache hit라고 한다). 자연스레 데이터베이스의 부하도 줄어든다.

캐시의 동작과정을 표현하면 위와 같다. 이와같은 전략을 읽기주도형 캐시전략(read-through caching startegy) 이라고 부른다. 이외에도 다양한 전략이 있는데, 캐시할 데이터의 종류, 크기 등 서비스에 적합한 전략을 선택하면 될것이다.
캐시 사용시 유의할점
캐시를 사용할땐 데이터 성격을 잘 알아야 한다. 데이터가 매우 빠르게 변한다면 일관성 문제로 캐시사용은 무용지물이니까. 따라서 다음을 유의해서 사용하도록 하자.
1. 데이터 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어난다.
2. 중요한 데이터는 지속적(디스크), 캐시는 휘발성 메모리이기 때문에 비영속적 데이터를 저장하는 용도로 사용한다.
3. 만료 정책을 마련해야 한다(그렇지 않으면 캐시에 계속 누적된다)
4. 일관성이 잘 유지되는지 유의한다
원본 저장소 수정시 캐시 데이터 수정까지 단일 트랜잭션에 있지 않다면 일관성 문제가 발생한다.
5. 장애 대처방안을 세운다.
캐시서버가 한대라면 해당 서버는 단일장애지점(SPOF, 특정 지점에서의 장애가 전체 시스템을 뻗게 만드는것)가 되어버릴 가능성이 있다. 따라서 여러지역에 걸쳐 캐시 서버를 분산한다.
6. 캐시 메모리 크기에 유의한다.
캐시메모리가 너무 작으면 데이터가 너무 자주 밀려 성능이 떨어진다. 이를 해결하기 위해 메모리를 과할당하기도 한다.
7. 데이터 방출
캐시가 꽉차면 기존 데이터 방출 후 새로운 데이터를 넣는다. 이때 방출할 데이터를 선택하는 알고리즘이 운영체제에서 자주봤던 LRU(Least Recently Used - 마지막으로 사용된 시점이 가장 오래된 데이터)이다. LFU, FIFO등 경우에 맞게 적용한다.
CDN(콘텐츠 전송 네트워크)
이미지나 비디오, CSS등 정적인 콘텐츠들이 있다. 그리고 이를 캐싱하기위해 CDN서비스를 이용할 수 있다.
글로벌 서비스인 유튜브를 생각해보자. 한 동영상이 전세계에서 재생되는데, 물리적으로 멀리 떨어진곳에서도 데이터를 빠르게 전달하기 위해서는 이러한 정적 콘텐츠의 캐싱이 필요할것이다.
클라이언트와 서버 사이에 두고, 동영상이나 이미지를 조회할때 cdn을 먼저 조회한다. 없다면 원본저장소에서 가져오는 방식이다. cdn사업자들은 전국 곳곳에 서버를 관리하고 있기 때문에 가장 가까운 서버에서 응답이 오도록 보장된다. 유튜브가 하나의 동영상을 끊김없이 글로벌하게 제공할 수 있는 이유중에 하나이다.

1. 사용자A가 이미지URL을 이용해 image.png에 접근한다.
2. CDN서버 캐시에 이미지가 없다면 원본서버에 요청해 파일을 가져온다. 원본서버는 웹서버일수도, 아마존S3와같은 온라인 저장소일수도 있다.
3. 원본서버가 파일을 CDN서버에 반환한다. 응답헤더에 파일의 TTL값을 함께 보낸다.
4. CDN서버는 파일 캐시 후 사용자 A에게 반환하고, 이미지는 TTL에 명시된 기간이 끝날때까지 캐시한다.
5. 사용자 B가 같은 이미지 요청을 CDN서버에 전송한다.
6. 만료되지 않은 이미지에 대한 요청은 캐시를 통해 처리된다.
(CF) 유의사항
보통 CDN은 제3 사업자에 의해 운영되므로 데이터 전송 양에 따라 요금이 부과된다. TTL의 적절한 설정으로 컨텐츠의 신선도를 유지하고 원본서버에 대한 빈번한 접속을 줄여야한다. cdn장애에 대한 대처방안도 구축이 필요하다.
여기까지 활용한 전체적인 흐름은 다음과 같다.

데이터센터 자동화
다음장으로 넘어가기 전에, 물리적인 관점에서도 생각해보자.
서버들이 모인 데이터센터에 불이난다면? 모든 서비스는 중단될것이다.
따라서 서버를 2개 이상의 데이터센터에 분배할 필요가 있다.

(CF.)
AWS의 경우는 Available Zone을 이용해 물리적 이중화가 가능하다. 서울리전에 a~d까지의 AZ를 운영하고있다.
또 Cloud다중화를 고려할수도 있다(AWS가 먹통이되면 문제니까)
문제점
DB의 경우, 각 클라우드마다 저장되는 데이터가 다를것이다. 따라서 메인으로 사용할 DB가 필요하다.
메인이 아닌 DB가 있는 클라우드의 경우, CDC와 같은 솔루션을 통해 DB를 지속적으로 동기화 하다가 메인DB의 클라우드가 서비스 중지되면 메인으로 승격해 사용할 수 있어야 한다. 그밖에도 양쪽 클라우드를 어떤 클라이언트가 어떤 조건일때 호출해야하는지도 결정해야하고, 그 결정은 어떤 클라우드 서버에서 할지도 결정해야하기 때문에 복잡한 구조가 필요하다.
'CS > 대규모 시스템 설계' 카테고리의 다른 글
| [대규모 시스템 설계] 1-1. 아키텍처 설계 (4) | 2025.05.06 |
|---|