개발 일지/대규모 시스템 설계

[대규모 시스템 설계] 1-2. 아키텍처 설계

배발자 2023. 7. 20.
반응형

데이터베이스 다중화

대규모 시스템 설계에 있어서 가장 중요한 것 중 하나는 데이터를 어떻게 보관을 하냐이다. 보통은 서버 사이에 주(master) - 부(slave) 관계를 설정하고 데이터 원본은 주서버에, 사본은 부 서버에 저장하는 방식이다. 쉽게 말하면, 나루토를 보신 분들은 아시겠지만 나루토가 주(master)이고 그림자 분신술을 써서 만들어진 복제본들이 부(slave)인 것이다. 

 

쓰기 연산(write)은 주(mastser)에서만 지원을 하고 부(slave)에서는 master에서 사본을 전달받아 읽기 연산만을 지원한다. 필자가 프로젝트를 진행하면서 학습했던 내용은 데이터베이스에 데이터를 변경하고 삽입하는 연산보다는 읽기 연산의 비중이 훨씬 높다는 얘기들 들었다. 해당 포스팅을 보는 여러분들도 벌써 읽기 연산 한 번이 서버에 요청이 들어간 것이다. 이처럼 대부분의 애플리케이션에서 읽기 연산이 쓰기 연산보다 훨씬 많다면 어떻게 처리할까? 

 

부 (slave) 데이터베이스가 주 (master) 데이터베이스보다 많게 증설하고 읽기 연산을 분산 처리하면 되는 것이다. 

 

 

  1. 주-부 다중화 모델에서 모든 데이터 변경은 주 데이터 베이스 서버로, 읽기 연산은 부 데이터 베이스 서버들로 분산한다. 즉, 병렬로 처리될 수 있는 쿼리의 수가 늘어나므로, 성능이 좋아진다. 
  2. 데이터 베이스 서버 일부가 파괴되어도 다중화 시켜서 복구할 수 있다. (안정성, 가용성) 

 

그렇다면, 데이터베이스 서버 하나에 장애가 발생한다면 어떻게 복구할 수 있다는 것인가? 

 

Q. 부서버가 한 대인데 다운된 경우라면? 

A. 읽기 연산은 한시적으로 모두 주DB로 전달된다. 그리고 즉시 새로운 부DB 서버가 장애 서버를 대체한다. 

 

Q. 부서버가 여러 대인 경우라면? 

A. 읽기 연산은 나머지 부DB 서버들로 분산되고, 새로운 부DB 서버가 장애 서버를 대체한다. 

 

Q. 주 DB서버가 다운되고, 한 대의 부 DB만 있는 경우라면? 

A. 부 DB 서버가 새로운 주 DB 서버가 될 것이며, 모든 DB 연산은 일시적으로 새로운 주 서버상에서 수행된다. 그리고 새로운 부 서버가 추가된다. 

 

만약 부 서버가 주 서버를 대체하게 되는 경우, 최신 상태가 아닐 수도 있다. 이때는 복구 스크립트를 돌려서 추가해야한다. 다중 마스터 원형 다중화 방식을 도입하면 이런 상황에 대처하는 데 도움이 될 수 있다고 한다.

해당 내용은 추후 포스팅 하도록 하겠다. (필자도 공부해야한다..)

 

 

 

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

 

  1. 사용자는 DNS로부터 로드밸런서 공개 IP 주소를 받는다. 
  2. 사용자는 해당 IP 주소를 사용해 로드밸런서에 접속한다. 
  3. HTTP 요청은 서버 1 or 서버 2로 전달된다. 
  4. 웹 서버는 사용자의 데이터를 부 DB 서버에서 읽는다. 
  5. 웹 서버는 데이터 변경 연산은 주 DB 서버로 전달하여, create, delete, update 연산 등이 진행된다. 

 


 

지금까지 웹 계층과 데이터 계층을 어떻게 분리하는지에 대해 어느정도 알아보았다. 대충 흐름은 알겠는데, 어떻게 응답시간을 개선할 수 있을지 고민을 해봐야한다. 응답 시간은 캐시, 콘텐츠 전송 네트워크 CDN을 활용하면 개선할 수 있다. 

 

캐시

필자는 프로젝트를 진행하면서 레디스를 사용해본적이 있다. 왜 캐시를 사용하는지부터 설명을 하자면, 서비스에서 DB의 데이터를 불러오는 작업은 시간이 많이 걸리는 일이다. 

 

학창시절, 교실에 있는 사물함을 많이 이용해봤을 거다. 만약 국어 수업이 있는 날에는 국어책을 사물함에 미리 넣어놓는다. 만약 사물함에 없다면? 집에 가서 들고와야지 뭐... 사물함에 넣어놓은 친구들은 10초, 집에 있으면 20분? 걸리겠네

 

집이 디스크고, 사물함이 캐시라고 생각하자. 즉, 캐시는 값비싼 연산 결과 또는 자주 참조되는 데이터를 메모리 안에 두고, 뒤이은 요청이 보다 빨리 처리될 수 있도록 하는 저장소다. 

 

 

캐시가 어떻게 적용되는지 위의 그림을 보고 이해해보자.아까 예시로 들었던 "교실에서 국어책 가져오기"을 대입하면서 읽어보면 쉽게 이해할 것이다. 위와 같은 캐시 전략을 읽기 주도형 캐시 전략(read-through caching strategy)이라고 부른다. 이것 이외에도 다양한 캐시 전략이 있다고 하는데, 캐시할 데이터의 종류, 크기 등 서비스에 맞는 캐시 전략을 선택하면 된다. 

 

 

캐시 유의점

 

1. 데이터 갱신은 자주 일어나지 않지만 참조는 빈번하게 일어난다. 

 

2. 중요한 데이터는 지속적 저장소 (디스트), 캐시는 휘발성 메모리이기 때문에 비영속적 데이터 저장 용도

 

3. 만료 정책 마련해야한다.

만료 정책이 없으면 데이터는 캐시에 계속 남게 되므로! 

 

4. 일관성이 잘 유지되는가?

저장소의 원본 갱신할 때 캐시를 갱신하는 연산이 단일 트랜잭션으로 처리되지 않는 경우 일관성에 문제 발생할 수 있다. 

 

5. 장애에는 어떻게 대처할건지?

만약 캐시 서버를 한 대만 둔다면 해당 서버는 단일 장애 지점(Single Point Of Failure, SPOF)이 되어버릴 가능성이  있다. 즉, 어떤 특정 지점에서의 장애가 전체 시스템을 뻗게 만드는 경우, 해당 지점을 단일 장애지점이라고 부른다. SPOF를 피하려면 여러 지역에 걸쳐 캐시 서버를 분산한다. 

 

6. 캐시 메모리를 얼마나 크게 잡을것인가? 

캐시 메모리가 너무 작으면 데이터가 너무 자주 캐시에 밀려나버린다. 즉, 성능이 떨어지게 되는데, 이를 해결하기 위해 캐시 메모리를 과할당(overprovision)하는 방법이 있다.

 

7. 데이터 방출 

캐시가 꽉 차버리면 기존의 데이터를 방출하고 새로운 데이터를 넣어야한다. 이때 가장 널리 알려져있는 알고리즘이 LRU이다. Least Recently Used  - 마지막으로 사용된 시점이 가장 오래된 데이터를 내보내는 정책이다. 다른 정책으로 LFU, FIFO 같은 것도 있고, 경우에 맞게 적용 가능하다. 

 

 

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

CDN 은 정적 콘텐츠를 전송하는 데 쓰이는, 지리적으로 분산된 서버의 네트워크이다. 이미지, 비디오, CSS 등을 캐시할 수 있는데 어떤 사용자가 웹 사이트에 방문한다고 가정하자. 

 

  1. 사용자 A가 이미지 URL을 이용해 image.png에 접근
  2. CDN 서버의 캐시에 이미지가 없으면 원본 서버에 요청하여 파일을 가져온다. 원본 서버는 웹 서버일 수도 있고 아마존 S3 같은 온라인 저장소일 수도 있다. 필자는 프로젝트를 진행할 때 CDN 말고 S3만 활용해서 이미지를 불러왔었다.
  3. 원본 서버가 파일을 CDN 서버에 반환한다. 응답 헤더에 파일이 얼마나 오래 캐시될 수 있는지 TTL(TimeToLive) 값이 들어있다. 
  4. CDN 서버는 파일 캐시 후 사용자 A에게 반환하고 이미지는 TTL에 명시된 시간이 끝날 때까지 캐시.
  5. 사용자 B가 같은 이미지에 대한 요청을 CDN 서버에 전송. 
  6. 만료되지 않은 이미지에 대한 요청은 캐시를 통해 처리. 

 

* CDN 고려해야 할 사항

보통 CDN은 제3 사업자에 의해 운영되므로, 데이터 전송 양에 따라 요금을 내니 적절하게 활용해야한다. 만료 시한 설정을 적절히 하여 컨텐츠의 신선도를 유지하고, 원본 서버에 빈번한 접속을 지양해야한다. 또한, CDN 장애에 대한 대처 방안을 구축해야한다. 

 

마지막으로 전체 흐름을 그림으로 이해해보자. 

 

 

반응형

댓글